LTP GCOV extension - code coverage report
Current view: directory - alg - gdalgeoloc.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 287
Code covered: 72.1 % Executed lines: 207

       1                 : /******************************************************************************
       2                 :  * $Id: gdalgeoloc.cpp 18948 2010-02-27 21:27:53Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL
       5                 :  * Purpose:  Implements Geolocation array based transformer.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2006, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "gdal_priv.h"
      31                 : #include "gdal_alg.h"
      32                 : 
      33                 : #ifdef SHAPE_DEBUG
      34                 : #include "/u/pkg/shapelib/shapefil.h"
      35                 : 
      36                 : SHPHandle hSHP = NULL;
      37                 : DBFHandle hDBF = NULL;
      38                 : #endif
      39                 : 
      40                 : CPL_CVSID("$Id: gdalgeoloc.cpp 18948 2010-02-27 21:27:53Z rouault $");
      41                 : 
      42                 : CPL_C_START
      43                 : CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg );
      44                 : void *GDALDeserializeGeoLocTransformer( CPLXMLNode *psTree );
      45                 : CPL_C_END
      46                 : 
      47                 : /************************************************************************/
      48                 : /* ==================================================================== */
      49                 : /*         GDALGeoLocTransformer                        */
      50                 : /* ==================================================================== */
      51                 : /************************************************************************/
      52                 : 
      53                 : typedef struct {
      54                 : 
      55                 :     GDALTransformerInfo sTI;
      56                 : 
      57                 :     int         bReversed;
      58                 : 
      59                 :     // Map from target georef coordinates back to geolocation array
      60                 :     // pixel line coordinates.  Built only if needed.
      61                 : 
      62                 :     int         nBackMapWidth;
      63                 :     int         nBackMapHeight;
      64                 :     double      adfBackMapGeoTransform[6]; // maps georef to pixel/line.
      65                 :     float       *pafBackMapX;
      66                 :     float       *pafBackMapY;
      67                 : 
      68                 :     // geolocation bands.
      69                 :     
      70                 :     GDALDatasetH     hDS_X;
      71                 :     GDALRasterBandH  hBand_X;
      72                 :     GDALDatasetH     hDS_Y;
      73                 :     GDALRasterBandH  hBand_Y;
      74                 : 
      75                 :     // Located geolocation data. 
      76                 :     int              nGeoLocXSize;
      77                 :     int              nGeoLocYSize;
      78                 :     double           *padfGeoLocX;
      79                 :     double           *padfGeoLocY;
      80                 : 
      81                 :     double           dfNoDataX;
      82                 :     double           dfNoDataY;
      83                 :     
      84                 :     // geolocation <-> base image mapping.
      85                 :     double           dfPIXEL_OFFSET;
      86                 :     double           dfPIXEL_STEP;
      87                 :     double           dfLINE_OFFSET;
      88                 :     double           dfLINE_STEP;
      89                 : 
      90                 :     char **          papszGeolocationInfo;
      91                 : 
      92                 : } GDALGeoLocTransformInfo;
      93                 : 
      94                 : /************************************************************************/
      95                 : /*                         GeoLocLoadFullData()                         */
      96                 : /************************************************************************/
      97                 : 
      98               2 : static int GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )
      99                 : 
     100                 : {
     101                 :     int nXSize, nYSize;
     102                 : 
     103               2 :     int nXSize_XBand = GDALGetRasterXSize( psTransform->hDS_X );
     104               2 :     int nYSize_XBand = GDALGetRasterYSize( psTransform->hDS_X );
     105               2 :     int nXSize_YBand = GDALGetRasterXSize( psTransform->hDS_Y );
     106               2 :     int nYSize_YBand = GDALGetRasterYSize( psTransform->hDS_Y );
     107               2 :     if (nYSize_XBand == 1 && nYSize_YBand == 1)
     108                 :     {
     109               0 :         nXSize = nXSize_XBand;
     110               0 :         nYSize = nXSize_YBand;
     111                 :     }
     112                 :     else
     113                 :     {
     114               2 :         nXSize = nXSize_XBand;
     115               2 :         nYSize = nYSize_XBand;
     116                 :     }
     117                 : 
     118               2 :     psTransform->nGeoLocXSize = nXSize;
     119               2 :     psTransform->nGeoLocYSize = nYSize;
     120                 :     
     121                 :     psTransform->padfGeoLocY = (double *) 
     122               2 :         VSIMalloc3(sizeof(double), nXSize, nYSize);
     123                 :     psTransform->padfGeoLocX = (double *) 
     124               2 :         VSIMalloc3(sizeof(double), nXSize, nYSize);
     125                 :     
     126               2 :     if( psTransform->padfGeoLocX == NULL ||
     127                 :         psTransform->padfGeoLocY == NULL )
     128                 :     {
     129                 :         CPLError(CE_Failure, CPLE_OutOfMemory,
     130               0 :                  "GeoLocLoadFullData : Out of memory");
     131               0 :         return FALSE;
     132                 :     }
     133                 : 
     134               2 :     if (nYSize_XBand == 1 && nYSize_YBand == 1)
     135                 :     {
     136                 :         /* Case of regular grid */
     137                 :         /* The XBAND contains the x coordinates for all lines */
     138                 :         /* The YBAND contains the y coordinates for all columns */
     139                 : 
     140               0 :         double* padfTempX = (double*)VSIMalloc2(nXSize, sizeof(double));
     141               0 :         double* padfTempY = (double*)VSIMalloc2(nYSize, sizeof(double));
     142               0 :         if (padfTempX == NULL || padfTempY == NULL)
     143                 :         {
     144               0 :             CPLFree(padfTempX);
     145               0 :             CPLFree(padfTempY);
     146                 :             CPLError(CE_Failure, CPLE_OutOfMemory,
     147               0 :                  "GeoLocLoadFullData : Out of memory");
     148               0 :             return FALSE;
     149                 :         }
     150                 : 
     151               0 :         CPLErr eErr = CE_None;
     152                 : 
     153                 :         eErr = GDALRasterIO( psTransform->hBand_X, GF_Read, 
     154                 :                              0, 0, nXSize, 1,
     155                 :                              padfTempX, nXSize, 1, 
     156               0 :                              GDT_Float64, 0, 0 );
     157                 : 
     158                 :         int i,j;
     159               0 :         for(j=0;j<nYSize;j++)
     160                 :         {
     161                 :             memcpy( psTransform->padfGeoLocX + j * nXSize,
     162                 :                     padfTempX,
     163               0 :                     nXSize * sizeof(double) );
     164                 :         }
     165                 : 
     166               0 :         if (eErr == CE_None)
     167                 :         {
     168                 :             eErr = GDALRasterIO( psTransform->hBand_Y, GF_Read, 
     169                 :                                 0, 0, nYSize, 1,
     170                 :                                 padfTempY, nYSize, 1, 
     171               0 :                                 GDT_Float64, 0, 0 );
     172                 : 
     173               0 :             for(j=0;j<nYSize;j++)
     174                 :             {
     175               0 :                 for(i=0;i<nXSize;i++)
     176                 :                 {
     177               0 :                     psTransform->padfGeoLocY[j * nXSize + i] = padfTempY[j];
     178                 :                 }
     179                 :             }
     180                 :         }
     181                 : 
     182               0 :         CPLFree(padfTempX);
     183               0 :         CPLFree(padfTempY);
     184                 : 
     185               0 :         if (eErr != CE_None)
     186               0 :             return FALSE;
     187                 :     }
     188                 :     else
     189                 :     {
     190               2 :         if( GDALRasterIO( psTransform->hBand_X, GF_Read, 
     191                 :                         0, 0, nXSize, nYSize,
     192                 :                         psTransform->padfGeoLocX, nXSize, nYSize, 
     193                 :                         GDT_Float64, 0, 0 ) != CE_None 
     194                 :             || GDALRasterIO( psTransform->hBand_Y, GF_Read, 
     195                 :                             0, 0, nXSize, nYSize,
     196                 :                             psTransform->padfGeoLocY, nXSize, nYSize, 
     197                 :                             GDT_Float64, 0, 0 ) != CE_None )
     198               0 :             return FALSE;
     199                 :     }
     200                 : 
     201                 :     psTransform->dfNoDataX = GDALGetRasterNoDataValue( psTransform->hBand_X, 
     202               2 :                                                        NULL );
     203                 :     psTransform->dfNoDataY = GDALGetRasterNoDataValue( psTransform->hBand_Y, 
     204               2 :                                                        NULL );
     205                 : 
     206               2 :     return TRUE;
     207                 : }
     208                 : 
     209                 : /************************************************************************/
     210                 : /*                       GeoLocGenerateBackMap()                        */
     211                 : /************************************************************************/
     212                 : 
     213               2 : static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
     214                 : 
     215                 : {
     216               2 :     int nXSize = psTransform->nGeoLocXSize;
     217               2 :     int nYSize = psTransform->nGeoLocYSize;
     218               2 :     int nMaxIter = 3;
     219                 : 
     220                 : /* -------------------------------------------------------------------- */
     221                 : /*      Scan forward map for lat/long extents.                          */
     222                 : /* -------------------------------------------------------------------- */
     223               2 :     double dfMinX=0, dfMaxX=0, dfMinY=0, dfMaxY=0;
     224               2 :     int i, bInit = FALSE;
     225                 : 
     226            4682 :     for( i = nXSize * nYSize - 1; i >= 0; i-- )
     227                 :     {
     228            4680 :         if( psTransform->padfGeoLocX[i] != psTransform->dfNoDataX )
     229                 :         {
     230            4680 :             if( bInit )
     231                 :             {
     232            4678 :                 dfMinX = MIN(dfMinX,psTransform->padfGeoLocX[i]);
     233            4678 :                 dfMaxX = MAX(dfMaxX,psTransform->padfGeoLocX[i]);
     234            4678 :                 dfMinY = MIN(dfMinY,psTransform->padfGeoLocY[i]);
     235            4678 :                 dfMaxY = MAX(dfMaxY,psTransform->padfGeoLocY[i]);
     236                 :             }
     237                 :             else
     238                 :             {
     239               2 :                 bInit = TRUE;
     240               2 :                 dfMinX = dfMaxX = psTransform->padfGeoLocX[i];
     241               2 :                 dfMinY = dfMaxY = psTransform->padfGeoLocY[i];
     242                 :             }
     243                 :         }
     244                 :     }
     245                 : 
     246                 : /* -------------------------------------------------------------------- */
     247                 : /*      Decide on resolution for backmap.  We aim for slightly          */
     248                 : /*      higher resolution than the source but we can't easily           */
     249                 : /*      establish how much dead space there is in the backmap, so it    */
     250                 : /*      is approximate.                                                 */
     251                 : /* -------------------------------------------------------------------- */
     252               2 :     double dfTargetPixels = (nXSize * nYSize * 1.3);
     253                 :     double dfPixelSize = sqrt((dfMaxX - dfMinX) * (dfMaxY - dfMinY) 
     254               2 :                               / dfTargetPixels);
     255                 :     int nBMXSize, nBMYSize;
     256                 : 
     257                 :     nBMYSize = psTransform->nBackMapHeight = 
     258               2 :         (int) ((dfMaxY - dfMinY) / dfPixelSize + 1);
     259                 :     nBMXSize= psTransform->nBackMapWidth =  
     260               2 :         (int) ((dfMaxX - dfMinX) / dfPixelSize + 1);
     261                 : 
     262               2 :     if (nBMXSize > INT_MAX / nBMYSize)
     263                 :     {
     264                 :         CPLError(CE_Failure, CPLE_AppDefined, "Int overflow : %d x %d",
     265               0 :                  nBMXSize, nBMYSize);
     266               0 :         return FALSE;
     267                 :     }
     268                 : 
     269               2 :     dfMinX -= dfPixelSize/2.0;
     270               2 :     dfMaxY += dfPixelSize/2.0;
     271                 : 
     272               2 :     psTransform->adfBackMapGeoTransform[0] = dfMinX;
     273               2 :     psTransform->adfBackMapGeoTransform[1] = dfPixelSize;
     274               2 :     psTransform->adfBackMapGeoTransform[2] = 0.0;
     275               2 :     psTransform->adfBackMapGeoTransform[3] = dfMaxY;
     276               2 :     psTransform->adfBackMapGeoTransform[4] = 0.0;
     277               2 :     psTransform->adfBackMapGeoTransform[5] = -dfPixelSize;
     278                 : 
     279                 : /* -------------------------------------------------------------------- */
     280                 : /*      Allocate backmap, and initialize to nodata value (-1.0).        */
     281                 : /* -------------------------------------------------------------------- */
     282                 :     GByte  *pabyValidFlag;
     283                 : 
     284                 :     pabyValidFlag = (GByte *) 
     285               2 :         VSICalloc(nBMXSize, nBMYSize); 
     286                 : 
     287                 :     psTransform->pafBackMapX = (float *) 
     288               2 :         VSIMalloc3(nBMXSize, nBMYSize, sizeof(float)); 
     289                 :     psTransform->pafBackMapY = (float *) 
     290               2 :         VSIMalloc3(nBMXSize, nBMYSize, sizeof(float)); 
     291                 : 
     292               2 :     if( pabyValidFlag == NULL ||
     293                 :         psTransform->pafBackMapX == NULL ||
     294                 :         psTransform->pafBackMapY == NULL )
     295                 :     {
     296                 :         CPLError( CE_Failure, CPLE_OutOfMemory, 
     297                 :                   "Unable to allocate %dx%d back-map for geolocation array transformer.",
     298               0 :                   nBMXSize, nBMYSize );
     299               0 :         CPLFree( pabyValidFlag );
     300               0 :         return FALSE;
     301                 :     }
     302                 : 
     303            6258 :     for( i = nBMXSize * nBMYSize - 1; i >= 0; i-- )
     304                 :     {
     305            6256 :         psTransform->pafBackMapX[i] = -1.0;
     306            6256 :         psTransform->pafBackMapY[i] = -1.0;
     307                 :     }
     308                 : 
     309                 : /* -------------------------------------------------------------------- */
     310                 : /*      Run through the whole geoloc array forward projecting and       */
     311                 : /*      pushing into the backmap.                                       */
     312                 : /*      Initialise to the nMaxIter+1 value so we can spot genuinely     */
     313                 : /*      valid pixels in the hole-filling loop.                          */
     314                 : /* -------------------------------------------------------------------- */
     315                 :     int iBMX, iBMY;
     316                 :     int iX, iY;
     317                 : 
     318              80 :     for( iY = 0; iY < nYSize; iY++ )
     319                 :     {
     320            4758 :         for( iX = 0; iX < nXSize; iX++ )
     321                 :         {
     322            4680 :             if( psTransform->padfGeoLocX[iX + iY * nXSize] 
     323                 :                 == psTransform->dfNoDataX )
     324               0 :                 continue;
     325                 : 
     326            4680 :             i = iX + iY * nXSize;
     327                 : 
     328            4680 :             iBMX = (int) ((psTransform->padfGeoLocX[i] - dfMinX) / dfPixelSize);
     329            4680 :             iBMY = (int) ((dfMaxY - psTransform->padfGeoLocY[i]) / dfPixelSize);
     330                 : 
     331            4680 :             if( iBMX < 0 || iBMY < 0 || iBMX >= nBMXSize || iBMY >= nBMYSize )
     332               2 :                 continue;
     333                 : 
     334                 :             psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] = 
     335            4678 :                 (float)(iX * psTransform->dfPIXEL_STEP + psTransform->dfPIXEL_OFFSET);
     336                 :             psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] = 
     337            4678 :                 (float)(iY * psTransform->dfLINE_STEP + psTransform->dfLINE_OFFSET);
     338                 : 
     339            4678 :             pabyValidFlag[iBMX + iBMY * nBMXSize] = nMaxIter+1;
     340                 : 
     341                 :         }
     342                 :     }
     343                 : 
     344                 : /* -------------------------------------------------------------------- */
     345                 : /*      Now, loop over the backmap trying to fill in holes with         */
     346                 : /*      nearby values.                                                  */
     347                 : /* -------------------------------------------------------------------- */
     348                 :     int iIter;
     349                 :     int nNumValid, nExpectedValid;
     350                 : 
     351               8 :     for( iIter = 0; iIter < nMaxIter; iIter++ )
     352                 :     {
     353               6 :         nNumValid = 0;
     354               6 :         nExpectedValid = (nBMYSize - 2) * (nBMXSize - 2);
     355             270 :         for( iBMY = 1; iBMY < nBMYSize-1; iBMY++ )
     356                 :         {
     357           17688 :             for( iBMX = 1; iBMX < nBMXSize-1; iBMX++ )
     358                 :             {
     359                 :                 // if this point is already set, ignore it. 
     360           17424 :                 if( pabyValidFlag[iBMX + iBMY*nBMXSize] )
     361                 :                 {
     362           12860 :                     nNumValid++;
     363           12860 :                     continue;
     364                 :                 }
     365                 : 
     366            4564 :                 int nCount = 0;
     367            4564 :                 double dfXSum = 0.0, dfYSum = 0.0;
     368            4564 :                 int nMarkedAsGood = nMaxIter - iIter;
     369                 : 
     370                 :                 // left?
     371            4564 :                 if( pabyValidFlag[iBMX-1+iBMY*nBMXSize] > nMarkedAsGood )
     372                 :                 {
     373             788 :                     dfXSum += psTransform->pafBackMapX[iBMX-1+iBMY*nBMXSize];
     374             788 :                     dfYSum += psTransform->pafBackMapY[iBMX-1+iBMY*nBMXSize];
     375             788 :                     nCount++;
     376                 :                 }
     377                 :                 // right?
     378            4564 :                 if( pabyValidFlag[iBMX+1+iBMY*nBMXSize] > nMarkedAsGood )
     379                 :                 {
     380             812 :                     dfXSum += psTransform->pafBackMapX[iBMX+1+iBMY*nBMXSize];
     381             812 :                     dfYSum += psTransform->pafBackMapY[iBMX+1+iBMY*nBMXSize];
     382             812 :                     nCount++;
     383                 :                 }
     384                 :                 // top?
     385            4564 :                 if( pabyValidFlag[iBMX+(iBMY-1)*nBMXSize] > nMarkedAsGood )
     386                 :                 {
     387             756 :                     dfXSum += psTransform->pafBackMapX[iBMX+(iBMY-1)*nBMXSize];
     388             756 :                     dfYSum += psTransform->pafBackMapY[iBMX+(iBMY-1)*nBMXSize];
     389             756 :                     nCount++;
     390                 :                 }
     391                 :                 // bottom?
     392            4564 :                 if( pabyValidFlag[iBMX+(iBMY+1)*nBMXSize] > nMarkedAsGood )
     393                 :                 {
     394             736 :                     dfXSum += psTransform->pafBackMapX[iBMX+(iBMY+1)*nBMXSize];
     395             736 :                     dfYSum += psTransform->pafBackMapY[iBMX+(iBMY+1)*nBMXSize];
     396             736 :                     nCount++;
     397                 :                 }
     398                 :                 // top-left?
     399            4564 :                 if( pabyValidFlag[iBMX-1+(iBMY-1)*nBMXSize] > nMarkedAsGood )
     400                 :                 {
     401             908 :                     dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY-1)*nBMXSize];
     402             908 :                     dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY-1)*nBMXSize];
     403             908 :                     nCount++;
     404                 :                 }
     405                 :                 // top-right?
     406            4564 :                 if( pabyValidFlag[iBMX+1+(iBMY-1)*nBMXSize] > nMarkedAsGood )
     407                 :                 {
     408             778 :                     dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY-1)*nBMXSize];
     409             778 :                     dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY-1)*nBMXSize];
     410             778 :                     nCount++;
     411                 :                 }
     412                 :                 // bottom-left?
     413            4564 :                 if( pabyValidFlag[iBMX-1+(iBMY+1)*nBMXSize] > nMarkedAsGood )
     414                 :                 {
     415             734 :                     dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY+1)*nBMXSize];
     416             734 :                     dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY+1)*nBMXSize];
     417             734 :                     nCount++;
     418                 :                 }
     419                 :                 // bottom-right?
     420            4564 :                 if( pabyValidFlag[iBMX+1+(iBMY+1)*nBMXSize] > nMarkedAsGood )
     421                 :                 {
     422             916 :                     dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY+1)*nBMXSize];
     423             916 :                     dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY+1)*nBMXSize];
     424             916 :                     nCount++;
     425                 :                 }
     426                 : 
     427            4564 :                 if( nCount > 0 )
     428                 :                 {
     429            1702 :                     psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] = (float)(dfXSum/nCount);
     430            1702 :                     psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] = (float)(dfYSum/nCount);
     431                 :                     // genuinely valid points will have value iMaxIter+1
     432                 :                     // On each iteration mark newly valid points with a
     433                 :                     // descending value so that it will not be used on the
     434                 :                     // current iteration only on subsequent ones.
     435            1702 :                     pabyValidFlag[iBMX+iBMY*nBMXSize] = nMaxIter - iIter;
     436                 :                 }
     437                 :             }
     438                 :         }
     439               6 :         if (nNumValid == nExpectedValid)
     440               0 :             break;
     441                 :     }
     442                 : 
     443                 : #ifdef notdef
     444                 :     GDALDatasetH hBMDS = GDALCreate( GDALGetDriverByName( "GTiff" ),
     445                 :                                      "backmap.tif", nBMXSize, nBMYSize, 2, 
     446                 :                                      GDT_Float32, NULL );
     447                 :     GDALSetGeoTransform( hBMDS, psTransform->adfBackMapGeoTransform );
     448                 :     GDALRasterIO( GDALGetRasterBand(hBMDS,1), GF_Write, 
     449                 :                   0, 0, nBMXSize, nBMYSize, 
     450                 :                   psTransform->pafBackMapX, nBMXSize, nBMYSize, 
     451                 :                   GDT_Float32, 0, 0 );
     452                 :     GDALRasterIO( GDALGetRasterBand(hBMDS,2), GF_Write, 
     453                 :                   0, 0, nBMXSize, nBMYSize, 
     454                 :                   psTransform->pafBackMapY, nBMXSize, nBMYSize, 
     455                 :                   GDT_Float32, 0, 0 );
     456                 :     GDALClose( hBMDS );
     457                 : #endif
     458                 : 
     459               2 :     CPLFree( pabyValidFlag );
     460                 : 
     461               2 :     return TRUE;
     462                 : }
     463                 : 
     464                 : /************************************************************************/
     465                 : /*                         FindGeoLocPosition()                         */
     466                 : /************************************************************************/
     467                 : 
     468                 : #ifdef notdef 
     469                 : 
     470                 : /*
     471                 : This searching approach has been abandoned because it is too sensitive
     472                 : to discontinuities in the data.  Left in case it might be revived in 
     473                 : the future.
     474                 :  */
     475                 : 
     476                 : static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
     477                 :                                double dfGeoX, double dfGeoY,
     478                 :                                int nStartX, int nStartY, 
     479                 :                                double *pdfFoundX, double *pdfFoundY )
     480                 : 
     481                 : {
     482                 :     double adfPathX[5000], adfPathY[5000];
     483                 : 
     484                 :     if( psTransform->padfGeoLocX == NULL )
     485                 :         return FALSE;
     486                 : 
     487                 :     int nXSize = psTransform->nGeoLocXSize;
     488                 :     int nYSize = psTransform->nGeoLocYSize;
     489                 :     int nStepCount = 0;
     490                 : 
     491                 :     // Start in center if we don't have any provided info.
     492                 :     if( nStartX < 0 || nStartY < 0 
     493                 :         || nStartX >= nXSize || nStartY >= nYSize )
     494                 :     {
     495                 :         nStartX = nXSize / 2;
     496                 :         nStartY = nYSize / 2;
     497                 :     }
     498                 : 
     499                 :     nStartX = MIN(nStartX,nXSize-2);
     500                 :     nStartY = MIN(nStartY,nYSize-2);
     501                 : 
     502                 :     int iX = nStartX, iY = nStartY;
     503                 :     int iLastX = -1, iLastY = -1;
     504                 :     int iSecondLastX = -1, iSecondLastY = -1;
     505                 : 
     506                 :     while( nStepCount < MAX(nXSize,nYSize) )
     507                 :     {
     508                 :         int iXNext = -1, iYNext = -1;
     509                 :         double dfDeltaXRight, dfDeltaYRight, dfDeltaXDown, dfDeltaYDown;
     510                 : 
     511                 :         double *padfThisX = psTransform->padfGeoLocX + iX + iY * nXSize;
     512                 :         double *padfThisY = psTransform->padfGeoLocY + iX + iY * nXSize;
     513                 : 
     514                 :         double dfDeltaX = dfGeoX - *padfThisX;
     515                 :         double dfDeltaY = dfGeoY - *padfThisY;
     516                 : 
     517                 :         if( iX == nXSize-1 )
     518                 :         {
     519                 :             dfDeltaXRight = *(padfThisX) - *(padfThisX-1);
     520                 :             dfDeltaYRight = *(padfThisY) - *(padfThisY-1);
     521                 :         }
     522                 :         else
     523                 :         {
     524                 :             dfDeltaXRight = *(padfThisX+1) - *padfThisX;
     525                 :             dfDeltaYRight = *(padfThisY+1) - *padfThisY;
     526                 :         }
     527                 : 
     528                 :         if( iY == nYSize - 1 )
     529                 :         {
     530                 :             dfDeltaXDown = *(padfThisX) - *(padfThisX-nXSize);
     531                 :             dfDeltaYDown = *(padfThisY) - *(padfThisY-nXSize);
     532                 :         }
     533                 :         else
     534                 :         {
     535                 :             dfDeltaXDown = *(padfThisX+nXSize) - *padfThisX;
     536                 :             dfDeltaYDown = *(padfThisY+nXSize) - *padfThisY;
     537                 :         }
     538                 : 
     539                 :         double dfRightProjection = 
     540                 :             (dfDeltaXRight * dfDeltaX + dfDeltaYRight * dfDeltaY) 
     541                 :             / (dfDeltaXRight*dfDeltaXRight + dfDeltaYRight*dfDeltaYRight);
     542                 : 
     543                 :         double dfDownProjection = 
     544                 :             (dfDeltaXDown * dfDeltaX + dfDeltaYDown * dfDeltaY) 
     545                 :             / (dfDeltaXDown*dfDeltaXDown + dfDeltaYDown*dfDeltaYDown);
     546                 : 
     547                 :         // Are we in our target cell?
     548                 :         if( dfRightProjection >= 0.0 && dfRightProjection < 1.0 
     549                 :             && dfDownProjection >= 0.0 && dfDownProjection < 1.0 )
     550                 :         {
     551                 :             *pdfFoundX = iX + dfRightProjection;
     552                 :             *pdfFoundY = iY + dfDownProjection;
     553                 : 
     554                 :             return TRUE;
     555                 :         }
     556                 :             
     557                 :         if( ABS(dfRightProjection) > ABS(dfDownProjection) )
     558                 :         {
     559                 :             // Do we want to move right? 
     560                 :             if( dfRightProjection > 1.0 && iX < nXSize-1 )
     561                 :             {
     562                 :                 iXNext = iX + MAX(1,(int)(dfRightProjection - nStepCount)/2);
     563                 :                 iYNext = iY;
     564                 :             }
     565                 :             
     566                 :             // Do we want to move left? 
     567                 :             else if( dfRightProjection < 0.0 && iX > 0 )
     568                 :             {
     569                 :                 iXNext = iX - MAX(1,(int)(ABS(dfRightProjection) - nStepCount)/2);
     570                 :                 iYNext = iY;
     571                 :             }
     572                 :             
     573                 :             // Do we want to move down.
     574                 :             else if( dfDownProjection > 1.0 && iY < nYSize-1 )
     575                 :             {
     576                 :                 iXNext = iX;
     577                 :                 iYNext = iY + MAX(1,(int)(dfDownProjection - nStepCount)/2);
     578                 :             }
     579                 :             
     580                 :             // Do we want to move up? 
     581                 :             else if( dfDownProjection < 0.0 && iY > 0 )
     582                 :             {
     583                 :                 iXNext = iX;
     584                 :                 iYNext = iY - MAX(1,(int)(ABS(dfDownProjection) - nStepCount)/2);
     585                 :             }
     586                 :             
     587                 :             // We aren't there, and we have no where to go
     588                 :             else
     589                 :             {
     590                 :                 return FALSE;
     591                 :             }
     592                 :         }
     593                 :         else
     594                 :         {
     595                 :             // Do we want to move down.
     596                 :             if( dfDownProjection > 1.0 && iY < nYSize-1 )
     597                 :             {
     598                 :                 iXNext = iX;
     599                 :                 iYNext = iY + MAX(1,(int)(dfDownProjection - nStepCount)/2);
     600                 :             }
     601                 :             
     602                 :             // Do we want to move up? 
     603                 :             else if( dfDownProjection < 0.0 && iY > 0 )
     604                 :             {
     605                 :                 iXNext = iX;
     606                 :                 iYNext = iY - MAX(1,(int)(ABS(dfDownProjection) - nStepCount)/2);
     607                 :             }
     608                 :             
     609                 :             // Do we want to move right? 
     610                 :             else if( dfRightProjection > 1.0 && iX < nXSize-1 )
     611                 :             {
     612                 :                 iXNext = iX + MAX(1,(int)(dfRightProjection - nStepCount)/2);
     613                 :                 iYNext = iY;
     614                 :             }
     615                 :             
     616                 :             // Do we want to move left? 
     617                 :             else if( dfRightProjection < 0.0 && iX > 0 )
     618                 :             {
     619                 :                 iXNext = iX - MAX(1,(int)(ABS(dfRightProjection) - nStepCount)/2);
     620                 :                 iYNext = iY;
     621                 :             }
     622                 :             
     623                 :             // We aren't there, and we have no where to go
     624                 :             else
     625                 :             {
     626                 :                 return FALSE;
     627                 :             }
     628                 :         }
     629                 :                 adfPathX[nStepCount] = iX;
     630                 :         adfPathY[nStepCount] = iY;
     631                 : 
     632                 :         nStepCount++;
     633                 :         iX = MAX(0,MIN(iXNext,nXSize-1));
     634                 :         iY = MAX(0,MIN(iYNext,nYSize-1));
     635                 : 
     636                 :         if( iX == iSecondLastX && iY == iSecondLastY )
     637                 :         {
     638                 :             // Are we *near* our target cell?
     639                 :             if( dfRightProjection >= -1.0 && dfRightProjection < 2.0
     640                 :                 && dfDownProjection >= -1.0 && dfDownProjection < 2.0 )
     641                 :             {
     642                 :                 *pdfFoundX = iX + dfRightProjection;
     643                 :                 *pdfFoundY = iY + dfDownProjection;
     644                 :                 
     645                 :                 return TRUE;
     646                 :             }
     647                 : 
     648                 : #ifdef SHAPE_DEBUG
     649                 :             if( hSHP != NULL )
     650                 :             {
     651                 :                 SHPObject *hObj;
     652                 :                 
     653                 :                 hObj = SHPCreateSimpleObject( SHPT_ARC, nStepCount,
     654                 :                                               adfPathX, adfPathY, NULL );
     655                 :                 SHPWriteObject( hSHP, -1, hObj );
     656                 :                 SHPDestroyObject( hObj );
     657                 :                 
     658                 :                 int iShape = DBFGetRecordCount( hDBF );
     659                 :                 DBFWriteDoubleAttribute( hDBF, iShape, 0, dfGeoX );
     660                 :                 DBFWriteDoubleAttribute( hDBF, iShape, 1, dfGeoY );
     661                 :             }
     662                 : #endif             
     663                 :             //CPLDebug( "GeoL", "Looping at step (%d) on search for %g,%g.", 
     664                 :             //          nStepCount, dfGeoX, dfGeoY );
     665                 :             return FALSE;
     666                 :         }
     667                 : 
     668                 :         iSecondLastX = iLastX;
     669                 :         iSecondLastY = iLastY;
     670                 : 
     671                 :         iLastX = iX;
     672                 :         iLastY = iY;
     673                 : 
     674                 :     }
     675                 : 
     676                 :     //CPLDebug( "GeoL", "Exceeded step count max (%d) on search for %g,%g.", 
     677                 :     //          MAX(nXSize,nYSize), 
     678                 :     //          dfGeoX, dfGeoY );
     679                 :     
     680                 : #ifdef SHAPE_DEBUG
     681                 :     if( hSHP != NULL )
     682                 :     {
     683                 :         SHPObject *hObj;
     684                 : 
     685                 :         hObj = SHPCreateSimpleObject( SHPT_ARC, nStepCount,
     686                 :                                       adfPathX, adfPathY, NULL );
     687                 :         SHPWriteObject( hSHP, -1, hObj );
     688                 :         SHPDestroyObject( hObj );
     689                 : 
     690                 :         int iShape = DBFGetRecordCount( hDBF );
     691                 :         DBFWriteDoubleAttribute( hDBF, iShape, 0, dfGeoX );
     692                 :         DBFWriteDoubleAttribute( hDBF, iShape, 1, dfGeoY );
     693                 :     }
     694                 : #endif
     695                 :               
     696                 :     return FALSE;
     697                 : }
     698                 : #endif /* def notdef */
     699                 : 
     700                 : 
     701                 : 
     702                 : /************************************************************************/
     703                 : /*                    GDALCreateGeoLocTransformer()                     */
     704                 : /************************************************************************/
     705                 : 
     706                 : void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS, 
     707                 :                                    char **papszGeolocationInfo,
     708               2 :                                    int bReversed )
     709                 : 
     710                 : {
     711                 :     GDALGeoLocTransformInfo *psTransform;
     712                 : 
     713               2 :     if( CSLFetchNameValue(papszGeolocationInfo,"PIXEL_OFFSET") == NULL
     714                 :         || CSLFetchNameValue(papszGeolocationInfo,"LINE_OFFSET") == NULL
     715                 :         || CSLFetchNameValue(papszGeolocationInfo,"PIXEL_STEP") == NULL
     716                 :         || CSLFetchNameValue(papszGeolocationInfo,"LINE_STEP") == NULL
     717                 :         || CSLFetchNameValue(papszGeolocationInfo,"X_BAND") == NULL
     718                 :         || CSLFetchNameValue(papszGeolocationInfo,"Y_BAND") == NULL )
     719                 :     {
     720                 :         CPLError( CE_Failure, CPLE_AppDefined,
     721               0 :                   "Missing some geolocation fields in GDALCreateGeoLocTransformer()" );
     722               0 :         return NULL;
     723                 :     }
     724                 : 
     725                 : /* -------------------------------------------------------------------- */
     726                 : /*      Initialize core info.                                           */
     727                 : /* -------------------------------------------------------------------- */
     728                 :     psTransform = (GDALGeoLocTransformInfo *) 
     729               2 :         CPLCalloc(sizeof(GDALGeoLocTransformInfo),1);
     730                 : 
     731               2 :     psTransform->bReversed = bReversed;
     732                 : 
     733               2 :     strcpy( psTransform->sTI.szSignature, "GTI" );
     734               2 :     psTransform->sTI.pszClassName = "GDALGeoLocTransformer";
     735               2 :     psTransform->sTI.pfnTransform = GDALGeoLocTransform;
     736               2 :     psTransform->sTI.pfnCleanup = GDALDestroyGeoLocTransformer;
     737               2 :     psTransform->sTI.pfnSerialize = GDALSerializeGeoLocTransformer;
     738               2 :     psTransform->papszGeolocationInfo = CSLDuplicate( papszGeolocationInfo );
     739                 : 
     740                 : /* -------------------------------------------------------------------- */
     741                 : /*      Pull geolocation info from the options/metadata.                */
     742                 : /* -------------------------------------------------------------------- */
     743                 :     psTransform->dfPIXEL_OFFSET = atof(CSLFetchNameValue( papszGeolocationInfo,
     744               2 :                                                           "PIXEL_OFFSET" ));
     745                 :     psTransform->dfLINE_OFFSET = atof(CSLFetchNameValue( papszGeolocationInfo,
     746               2 :                                                          "LINE_OFFSET" ));
     747                 :     psTransform->dfPIXEL_STEP = atof(CSLFetchNameValue( papszGeolocationInfo,
     748               2 :                                                         "PIXEL_STEP" ));
     749                 :     psTransform->dfLINE_STEP = atof(CSLFetchNameValue( papszGeolocationInfo,
     750               2 :                                                        "LINE_STEP" ));
     751                 : 
     752                 : /* -------------------------------------------------------------------- */
     753                 : /*      Establish access to geolocation dataset(s).                     */
     754                 : /* -------------------------------------------------------------------- */
     755                 :     const char *pszDSName = CSLFetchNameValue( papszGeolocationInfo, 
     756               2 :                                                "X_DATASET" );
     757               2 :     if( pszDSName != NULL )
     758                 :     {
     759               2 :         psTransform->hDS_X = GDALOpenShared( pszDSName, GA_ReadOnly );
     760                 :     }
     761                 :     else
     762                 :     {
     763               0 :         psTransform->hDS_X = hBaseDS;
     764               0 :         GDALReferenceDataset( psTransform->hDS_X );
     765                 :         psTransform->papszGeolocationInfo = 
     766                 :             CSLSetNameValue( psTransform->papszGeolocationInfo, 
     767                 :                              "X_DATASET", 
     768               0 :                              GDALGetDescription( hBaseDS ) );
     769                 :     }
     770                 : 
     771               2 :     pszDSName = CSLFetchNameValue( papszGeolocationInfo, "Y_DATASET" );
     772               2 :     if( pszDSName != NULL )
     773                 :     {
     774               2 :         psTransform->hDS_Y = GDALOpenShared( pszDSName, GA_ReadOnly );
     775                 :     }
     776                 :     else
     777                 :     {
     778               0 :         psTransform->hDS_Y = hBaseDS;
     779               0 :         GDALReferenceDataset( psTransform->hDS_Y );
     780                 :         psTransform->papszGeolocationInfo = 
     781                 :             CSLSetNameValue( psTransform->papszGeolocationInfo, 
     782                 :                              "Y_DATASET", 
     783               0 :                              GDALGetDescription( hBaseDS ) );
     784                 :     }
     785                 : 
     786               2 :     if (psTransform->hDS_X == NULL ||
     787                 :         psTransform->hDS_Y == NULL)
     788                 :     {
     789               0 :         GDALDestroyGeoLocTransformer( psTransform );
     790               0 :         return NULL;
     791                 :     }
     792                 : 
     793                 : /* -------------------------------------------------------------------- */
     794                 : /*      Get the band handles.                                           */
     795                 : /* -------------------------------------------------------------------- */
     796                 :     int nBand;
     797                 : 
     798               2 :     nBand = MAX(1,atoi(CSLFetchNameValue( papszGeolocationInfo, "X_BAND" )));
     799               2 :     psTransform->hBand_X = GDALGetRasterBand( psTransform->hDS_X, nBand );
     800                 : 
     801               2 :     nBand = MAX(1,atoi(CSLFetchNameValue( papszGeolocationInfo, "Y_BAND" )));
     802               2 :     psTransform->hBand_Y = GDALGetRasterBand( psTransform->hDS_Y, nBand );
     803                 : 
     804               2 :     if (psTransform->hBand_X == NULL ||
     805                 :         psTransform->hBand_Y == NULL)
     806                 :     {
     807               0 :         GDALDestroyGeoLocTransformer( psTransform );
     808               0 :         return NULL;
     809                 :     }
     810                 : 
     811                 : /* -------------------------------------------------------------------- */
     812                 : /*     Check that X and Y bands have the same dimensions                */
     813                 : /* -------------------------------------------------------------------- */
     814               2 :     int nXSize_XBand = GDALGetRasterXSize( psTransform->hDS_X );
     815               2 :     int nYSize_XBand = GDALGetRasterYSize( psTransform->hDS_X );
     816               2 :     int nXSize_YBand = GDALGetRasterXSize( psTransform->hDS_Y );
     817               2 :     int nYSize_YBand = GDALGetRasterYSize( psTransform->hDS_Y );
     818               2 :     if (nYSize_XBand == 1 || nYSize_YBand == 1)
     819                 :     {
     820               0 :         if (nYSize_XBand != 1 || nYSize_YBand != 1)
     821                 :         {
     822                 :             CPLError(CE_Failure, CPLE_AppDefined,
     823               0 :                  "X_BAND and Y_BAND should have both nYSize == 1");
     824               0 :             GDALDestroyGeoLocTransformer( psTransform );
     825               0 :             return NULL;
     826                 :         }
     827                 :     }
     828               2 :     else if (nXSize_XBand != nXSize_YBand ||
     829                 :              nYSize_XBand != nYSize_YBand )
     830                 :     {
     831                 :         CPLError(CE_Failure, CPLE_AppDefined,
     832               0 :                  "X_BAND and Y_BAND do not have the same dimensions");
     833               0 :         GDALDestroyGeoLocTransformer( psTransform );
     834               0 :         return NULL;
     835                 :     }
     836                 : 
     837               2 :     if (nXSize_XBand > INT_MAX / nYSize_XBand)
     838                 :     {
     839                 :         CPLError(CE_Failure, CPLE_AppDefined, "Int overflow : %d x %d",
     840               0 :                  nXSize_XBand, nYSize_XBand);
     841               0 :         GDALDestroyGeoLocTransformer( psTransform );
     842               0 :         return NULL;
     843                 :     }
     844                 : 
     845                 : /* -------------------------------------------------------------------- */
     846                 : /*      Load the geolocation array.                                     */
     847                 : /* -------------------------------------------------------------------- */
     848               2 :     if( !GeoLocLoadFullData( psTransform ) 
     849                 :         || !GeoLocGenerateBackMap( psTransform ) )
     850                 :     {
     851               0 :         GDALDestroyGeoLocTransformer( psTransform );
     852               0 :         return NULL;
     853                 :     }
     854                 : 
     855               2 :     return psTransform;
     856                 : }
     857                 : 
     858                 : /************************************************************************/
     859                 : /*                    GDALDestroyGeoLocTransformer()                    */
     860                 : /************************************************************************/
     861                 : 
     862               2 : void GDALDestroyGeoLocTransformer( void *pTransformAlg )
     863                 : 
     864                 : {
     865                 :     GDALGeoLocTransformInfo *psTransform = 
     866               2 :         (GDALGeoLocTransformInfo *) pTransformAlg;
     867                 : 
     868               2 :     CPLFree( psTransform->pafBackMapX );
     869               2 :     CPLFree( psTransform->pafBackMapY );
     870               2 :     CSLDestroy( psTransform->papszGeolocationInfo );
     871               2 :     CPLFree( psTransform->padfGeoLocX );
     872               2 :     CPLFree( psTransform->padfGeoLocY );
     873                 :              
     874               2 :     if( psTransform->hDS_X != NULL 
     875                 :         && GDALDereferenceDataset( psTransform->hDS_X ) == 0 )
     876               0 :             GDALClose( psTransform->hDS_X );
     877                 : 
     878               2 :     if( psTransform->hDS_Y != NULL 
     879                 :         && GDALDereferenceDataset( psTransform->hDS_Y ) == 0 )
     880               2 :             GDALClose( psTransform->hDS_Y );
     881                 : 
     882               2 :     CPLFree( pTransformAlg );
     883               2 : }
     884                 : 
     885                 : /************************************************************************/
     886                 : /*                        GDALGeoLocTransform()                         */
     887                 : /************************************************************************/
     888                 : 
     889                 : int GDALGeoLocTransform( void *pTransformArg, int bDstToSrc, 
     890                 :                          int nPointCount, 
     891                 :                          double *padfX, double *padfY, double *padfZ,
     892             260 :                          int *panSuccess )
     893                 : 
     894                 : {
     895                 :     GDALGeoLocTransformInfo *psTransform = 
     896             260 :         (GDALGeoLocTransformInfo *) pTransformArg;
     897                 : 
     898             260 :     if( psTransform->bReversed )
     899               0 :         bDstToSrc = !bDstToSrc;
     900                 : 
     901                 : /* -------------------------------------------------------------------- */
     902                 : /*      Do original pixel line to target geox/geoy.                     */
     903                 : /* -------------------------------------------------------------------- */
     904             260 :     if( !bDstToSrc )
     905                 :     {
     906               1 :         int i, nXSize = psTransform->nGeoLocXSize;
     907                 : 
     908               2 :         for( i = 0; i < nPointCount; i++ )
     909                 :         {
     910               1 :             if( !panSuccess[i] )
     911               0 :                 continue;
     912                 : 
     913               1 :             if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
     914                 :             {
     915               0 :                 panSuccess[i] = FALSE;
     916               0 :                 continue;
     917                 :             }
     918                 : 
     919                 :             double dfGeoLocPixel = (padfX[i] - psTransform->dfPIXEL_OFFSET) 
     920               1 :                 / psTransform->dfPIXEL_STEP;
     921                 :             double dfGeoLocLine = (padfY[i] - psTransform->dfLINE_OFFSET) 
     922               1 :                 / psTransform->dfLINE_STEP;
     923                 : 
     924                 :             int iX, iY;
     925                 : 
     926               1 :             iX = MAX(0,(int) dfGeoLocPixel);
     927               1 :             iX = MIN(iX,psTransform->nGeoLocXSize-2);
     928               1 :             iY = MAX(0,(int) dfGeoLocLine);
     929               1 :             iY = MIN(iY,psTransform->nGeoLocYSize-2);
     930                 : 
     931               1 :             double *padfGLX = psTransform->padfGeoLocX + iX + iY * nXSize;
     932               1 :             double *padfGLY = psTransform->padfGeoLocY + iX + iY * nXSize;
     933                 : 
     934                 :             // This assumes infinite extension beyond borders of available
     935                 :             // data based on closest grid square.
     936                 : 
     937                 :             padfX[i] = padfGLX[0] 
     938                 :                 + (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0])
     939               1 :                 + (dfGeoLocLine -iY) * (padfGLX[nXSize] - padfGLX[0]);
     940                 :             padfY[i] = padfGLY[0] 
     941                 :                 + (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0])
     942               1 :                 + (dfGeoLocLine -iY) * (padfGLY[nXSize] - padfGLY[0]);
     943                 : 
     944               1 :             panSuccess[i] = TRUE;
     945                 :         }
     946                 :     }
     947                 : 
     948                 : /* -------------------------------------------------------------------- */
     949                 : /*      geox/geoy to pixel/line using backmap.                          */
     950                 : /* -------------------------------------------------------------------- */
     951                 :     else
     952                 :     {
     953                 :         int i;
     954                 : 
     955           66705 :         for( i = 0; i < nPointCount; i++ )
     956                 :         {
     957           66446 :             if( !panSuccess[i] )
     958               0 :                 continue;
     959                 : 
     960           66446 :             if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
     961                 :             {
     962               0 :                 panSuccess[i] = FALSE;
     963               0 :                 continue;
     964                 :             }
     965                 : 
     966                 :             int iBMX, iBMY;
     967                 : 
     968                 :             iBMX = (int) ((padfX[i] - psTransform->adfBackMapGeoTransform[0])
     969           66446 :                           / psTransform->adfBackMapGeoTransform[1]);
     970                 :             iBMY = (int) ((padfY[i] - psTransform->adfBackMapGeoTransform[3])
     971           66446 :                           / psTransform->adfBackMapGeoTransform[5]);
     972                 : 
     973           66446 :             int iBM = iBMX + iBMY * psTransform->nBackMapWidth;
     974                 : 
     975           66446 :             if( iBMX < 0 || iBMY < 0 
     976                 :                 || iBMX >= psTransform->nBackMapWidth
     977                 :                 || iBMY >= psTransform->nBackMapHeight 
     978                 :                 || psTransform->pafBackMapX[iBM] < 0 )
     979                 :             {
     980           63969 :                 panSuccess[i] = FALSE;
     981           63969 :                 padfX[i] = HUGE_VAL;
     982           63969 :                 padfY[i] = HUGE_VAL;
     983           63969 :                 continue;
     984                 :             }
     985                 : 
     986            2477 :             padfX[i] = psTransform->pafBackMapX[iBM];
     987            2477 :             padfY[i] = psTransform->pafBackMapY[iBM];
     988            2477 :             panSuccess[i] = TRUE;
     989                 :         }
     990                 :     }
     991                 : 
     992                 : /* -------------------------------------------------------------------- */
     993                 : /*      geox/geoy to pixel/line using search algorithm.                 */
     994                 : /* -------------------------------------------------------------------- */
     995                 : #ifdef notdef
     996                 :     else
     997                 :     {
     998                 :         int i;
     999                 :         int nStartX = -1, nStartY = -1;
    1000                 : 
    1001                 : #ifdef SHAPE_DEBUG
    1002                 :         hSHP = SHPCreate( "tracks.shp", SHPT_ARC );
    1003                 :         hDBF = DBFCreate( "tracks.dbf" );
    1004                 :         DBFAddField( hDBF, "GEOX", FTDouble, 10, 4 );
    1005                 :         DBFAddField( hDBF, "GEOY", FTDouble, 10, 4 );
    1006                 : #endif
    1007                 :         for( i = 0; i < nPointCount; i++ )
    1008                 :         {
    1009                 :             double dfGeoLocX, dfGeoLocY;
    1010                 : 
    1011                 :             if( !panSuccess[i] )
    1012                 :                 continue;
    1013                 : 
    1014                 :             if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
    1015                 :             {
    1016                 :                 panSuccess[i] = FALSE;
    1017                 :                 continue;
    1018                 :             }
    1019                 : 
    1020                 :             if( !FindGeoLocPosition( psTransform, padfX[i], padfY[i], 
    1021                 :                                      -1, -1, &dfGeoLocX, &dfGeoLocY ) )
    1022                 :             {
    1023                 :                 padfX[i] = HUGE_VAL;
    1024                 :                 padfY[i] = HUGE_VAL;
    1025                 : 
    1026                 :                 panSuccess[i] = FALSE;
    1027                 :                 continue;
    1028                 :             }
    1029                 :             nStartX = (int) dfGeoLocX;
    1030                 :             nStartY = (int) dfGeoLocY;
    1031                 : 
    1032                 :             padfX[i] = dfGeoLocX * psTransform->dfPIXEL_STEP 
    1033                 :                 + psTransform->dfPIXEL_OFFSET;
    1034                 :             padfY[i] = dfGeoLocY * psTransform->dfLINE_STEP 
    1035                 :                 + psTransform->dfLINE_OFFSET;
    1036                 : 
    1037                 :             panSuccess[i] = TRUE;
    1038                 :         }
    1039                 : 
    1040                 : #ifdef SHAPE_DEBUG
    1041                 :         if( hSHP != NULL )
    1042                 :         {
    1043                 :             DBFClose( hDBF );
    1044                 :             hDBF = NULL;
    1045                 :             
    1046                 :             SHPClose( hSHP );
    1047                 :             hSHP = NULL;
    1048                 :         }
    1049                 : #endif
    1050                 :     }
    1051                 : #endif
    1052                 : 
    1053             260 :     return TRUE;
    1054                 : }
    1055                 : 
    1056                 : /************************************************************************/
    1057                 : /*                   GDALSerializeGeoLocTransformer()                   */
    1058                 : /************************************************************************/
    1059                 : 
    1060               0 : CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg )
    1061                 : 
    1062                 : {
    1063               0 :     VALIDATE_POINTER1( pTransformArg, "GDALSerializeGeoLocTransformer", NULL );
    1064                 : 
    1065                 :     CPLXMLNode *psTree;
    1066                 :     GDALGeoLocTransformInfo *psInfo = 
    1067               0 :         (GDALGeoLocTransformInfo *)(pTransformArg);
    1068                 : 
    1069               0 :     psTree = CPLCreateXMLNode( NULL, CXT_Element, "GeoLocTransformer" );
    1070                 : 
    1071                 : /* -------------------------------------------------------------------- */
    1072                 : /*      Serialize bReversed.                                            */
    1073                 : /* -------------------------------------------------------------------- */
    1074                 :     CPLCreateXMLElementAndValue( 
    1075                 :         psTree, "Reversed", 
    1076               0 :         CPLString().Printf( "%d", psInfo->bReversed ) );
    1077                 :                                  
    1078                 : /* -------------------------------------------------------------------- */
    1079                 : /*      geoloc metadata.                                                */
    1080                 : /* -------------------------------------------------------------------- */
    1081               0 :     char **papszMD = psInfo->papszGeolocationInfo;
    1082                 :     CPLXMLNode *psMD= CPLCreateXMLNode( psTree, CXT_Element, 
    1083               0 :                                         "Metadata" );
    1084                 : 
    1085               0 :     for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
    1086                 :     {
    1087                 :         const char *pszRawValue;
    1088                 :         char *pszKey;
    1089                 :         CPLXMLNode *psMDI;
    1090                 :                 
    1091               0 :         pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
    1092                 :                 
    1093               0 :         psMDI = CPLCreateXMLNode( psMD, CXT_Element, "MDI" );
    1094               0 :         CPLSetXMLValue( psMDI, "#key", pszKey );
    1095               0 :         CPLCreateXMLNode( psMDI, CXT_Text, pszRawValue );
    1096                 :                 
    1097               0 :         CPLFree( pszKey );
    1098                 :     }
    1099                 : 
    1100               0 :     return psTree;
    1101                 : }
    1102                 : 
    1103                 : /************************************************************************/
    1104                 : /*                   GDALDeserializeGeoLocTransformer()                 */
    1105                 : /************************************************************************/
    1106                 : 
    1107               1 : void *GDALDeserializeGeoLocTransformer( CPLXMLNode *psTree )
    1108                 : 
    1109                 : {
    1110                 :     void *pResult;
    1111                 :     int bReversed;
    1112               1 :     char **papszMD = NULL;
    1113                 :     CPLXMLNode *psMDI, *psMetadata;
    1114                 : 
    1115                 : /* -------------------------------------------------------------------- */
    1116                 : /*      Collect metadata.                                               */
    1117                 : /* -------------------------------------------------------------------- */
    1118               1 :     psMetadata = CPLGetXMLNode( psTree, "Metadata" );
    1119                 : 
    1120               1 :     if( psMetadata == NULL ||
    1121                 :         psMetadata->eType != CXT_Element
    1122                 :         || !EQUAL(psMetadata->pszValue,"Metadata") )
    1123               0 :         return NULL;
    1124                 :     
    1125              10 :     for( psMDI = psMetadata->psChild; psMDI != NULL; 
    1126                 :          psMDI = psMDI->psNext )
    1127                 :     {
    1128               9 :         if( !EQUAL(psMDI->pszValue,"MDI") 
    1129                 :             || psMDI->eType != CXT_Element 
    1130                 :             || psMDI->psChild == NULL 
    1131                 :             || psMDI->psChild->psNext == NULL 
    1132                 :             || psMDI->psChild->eType != CXT_Attribute
    1133                 :             || psMDI->psChild->psChild == NULL )
    1134               0 :             continue;
    1135                 :         
    1136                 :         papszMD = 
    1137                 :             CSLSetNameValue( papszMD, 
    1138                 :                              psMDI->psChild->psChild->pszValue, 
    1139               9 :                              psMDI->psChild->psNext->pszValue );
    1140                 :     }
    1141                 : 
    1142                 : /* -------------------------------------------------------------------- */
    1143                 : /*      Get other flags.                                                */
    1144                 : /* -------------------------------------------------------------------- */
    1145               1 :     bReversed = atoi(CPLGetXMLValue(psTree,"Reversed","0"));
    1146                 : 
    1147                 : /* -------------------------------------------------------------------- */
    1148                 : /*      Generate transformation.                                        */
    1149                 : /* -------------------------------------------------------------------- */
    1150               1 :     pResult = GDALCreateGeoLocTransformer( NULL, papszMD, bReversed );
    1151                 :     
    1152                 : /* -------------------------------------------------------------------- */
    1153                 : /*      Cleanup GCP copy.                                               */
    1154                 : /* -------------------------------------------------------------------- */
    1155               1 :     CSLDestroy( papszMD );
    1156                 : 
    1157               1 :     return pResult;
    1158                 : }

Generated by: LTP GCOV extension version 1.5