LCOV - code coverage report
Current view: directory - alg - gdalgeoloc.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 265 211 79.6 %
Date: 2010-01-09 Functions: 7 6 85.7 %

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

Generated by: LCOV version 1.7