GDAL的几个不错的函数

GDAL的几个不错的函数



#include "gdal_priv.h"
#include "gdal_alg.h"

#ifdef SHAPE_DEBUG
#include "/u/pkg/shapelib/shapefil.h"

SHPHandle hSHP = NULL;
DBFHandle hDBF = NULL;
#endif

CPL_CVSID("$Id: gdalgeoloc.cpp 12820 2007-11-16 22:39:26Z rouault $");

CPL_C_START
CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg );
void *GDALDeserializeGeoLocTransformer( CPLXMLNode *psTree );
CPL_C_END







typedef struct {

   GDALTransformerInfo sTI;

   int        bReversed;

    // Map from target georef coordinates back to geolocation array
    // pixel line coordinates.  Built only if needed.

   int        nBackMapWidth;
   int        nBackMapHeight;
   double     adfBackMapGeoTransform[6]; // maps georef to pixel/line.
   float      *pafBackMapX;
   float      *pafBackMapY;

    // geolocation bands.
   
   GDALDatasetH    hDS_X;
   GDALRasterBandH  hBand_X;
   GDALDatasetH    hDS_Y;
   GDALRasterBandH  hBand_Y;

    // Located geolocation data.
   int             nGeoLocXSize;
   int             nGeoLocYSize;
   double          *padfGeoLocX;
   double          *padfGeoLocY;

   double          dfNoDataX;
   double          dfNoDataY;
   
    // geolocation <-> base image mapping.
   double          dfPIXEL_OFFSET;
   double          dfPIXEL_STEP;
   double          dfLINE_OFFSET;
   double          dfLINE_STEP;

    char **         papszGeolocationInfo;

} GDALGeoLocTransformInfo;





static int GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )

{
    int nXSize = GDALGetRasterXSize( psTransform->hDS_X );
    int nYSize = GDALGetRasterYSize( psTransform->hDS_X );

   psTransform->nGeoLocXSize = nXSize;
   psTransform->nGeoLocYSize = nYSize;
   
   psTransform->padfGeoLocY = (double *)
       VSIMalloc(sizeof(double) * nXSize * nYSize);
   psTransform->padfGeoLocX = (double *)
       VSIMalloc(sizeof(double) * nXSize * nYSize);
   
    if( psTransform->padfGeoLocX == NULL )
    {
       CPLError(CE_Failure, CPLE_OutOfMemory,
                "GeoLocLoadFullData : Out of memory");
       return FALSE;
    }

    if( GDALRasterIO( psTransform->hBand_X, GF_Read,
                     0, 0, nXSize, nYSize,
                     psTransform->padfGeoLocX, nXSize, nYSize,
                     GDT_Float64, 0, 0 ) != CE_None
       || GDALRasterIO( psTransform->hBand_Y, GF_Read,
                        0, 0, nXSize, nYSize,
                        psTransform->padfGeoLocY, nXSize, nYSize,
                        GDT_Float64, 0, 0 ) != CE_None )
       return FALSE;

   psTransform->dfNoDataX = GDALGetRasterNoDataValue( psTransform->hBand_X,
                                                      NULL );
   psTransform->dfNoDataY = GDALGetRasterNoDataValue( psTransform->hBand_Y,
                                                      NULL );

    return TRUE;
}





static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )

{
    int nXSize = GDALGetRasterXSize( psTransform->hDS_X );
    int nYSize = GDALGetRasterYSize( psTransform->hDS_X );




    int iMaxIter = 3;
    if (getenv("MAXITER")) iMaxIter = atoi(getenv("MAXITER"));
    double dfBackmapSizeFactor = 1.3;
    if (getenv("BACKMAPFACTOR")) dfBackmapSizeFactor = atof(getenv("BACKMAPFACTOR"));
    if (getenv("DEBUG")) fprintf(stderr, "iMaxIter=%d, dfBackmapSizeFactor=%lf\n", iMaxIter, dfBackmapSizeFactor);




    double dfMinX=0, dfMaxX=0, dfMinY=0, dfMaxY=0;
    int i, bInit = FALSE;

    for( i = nXSize * nYSize - 1; i >= 0; i-- )
    {
       if( psTransform->padfGeoLocX[i] != psTransform->dfNoDataX )
       {
           if( bInit )
           {
               dfMinX = MIN(dfMinX,psTransform->padfGeoLocX[i]);
               dfMaxX = MAX(dfMaxX,psTransform->padfGeoLocX[i]);
               dfMinY = MIN(dfMinY,psTransform->padfGeoLocY[i]);
               dfMaxY = MAX(dfMaxY,psTransform->padfGeoLocY[i]);
           }
           else
           {
               bInit = TRUE;
               dfMinX = dfMaxX = psTransform->padfGeoLocX[i];
               dfMinY = dfMaxY = psTransform->padfGeoLocY[i];
           }
       }
    }







    double dfTargetPixels = (nXSize * nYSize * dfBackmapSizeFactor);
    double dfPixelSize = sqrt((dfMaxX - dfMinX) * (dfMaxY - dfMinY)
                             / dfTargetPixels);
    int nBMXSize, nBMYSize;

    nBMYSize = psTransform->nBackMapHeight =
       (int) ((dfMaxY - dfMinY) / dfPixelSize + 1);
    nBMXSize= psTransform->nBackMapWidth = 
       (int) ((dfMaxX - dfMinX) / dfPixelSize + 1);

    dfMinX -= dfPixelSize/2.0;
    dfMaxY += dfPixelSize/2.0;

   psTransform->adfBackMapGeoTransform[0] = dfMinX;
   psTransform->adfBackMapGeoTransform[1] = dfPixelSize;
   psTransform->adfBackMapGeoTransform[2] = 0.0;
   psTransform->adfBackMapGeoTransform[3] = dfMaxY;
   psTransform->adfBackMapGeoTransform[4] = 0.0;
   psTransform->adfBackMapGeoTransform[5] = -dfPixelSize;




   GByte  *pabyValidFlag;

   pabyValidFlag = (GByte *)
       VSIMalloc(nBMXSize * nBMYSize * sizeof(GByte));

   psTransform->pafBackMapX = (float *)
       VSIMalloc(nBMXSize * nBMYSize * sizeof(float));
   psTransform->pafBackMapY = (float *)
       VSIMalloc(nBMXSize * nBMYSize * sizeof(float));

    if( psTransform->pafBackMapY == NULL )
    {
       CPLError( CE_Failure, CPLE_OutOfMemory,
                 "Unable to allocate %dx%d back-map for geolocation array transformer.",
                 nBMXSize, nBMYSize );
       return FALSE;
    }

    for( i = nBMXSize * nBMYSize - 1; i >= 0; i-- )
    {
       psTransform->pafBackMapX[i] = -1.0;
       psTransform->pafBackMapY[i] = -1.0;
    }

    memset( pabyValidFlag, 0, nBMXSize * nBMYSize );






    int iBMX, iBMY;
    int iX, iY;

    for( iY = 0; iY < nYSize; iY++ )
    {
       for( iX = 0; iX < nXSize; iX++ )
       {
           if( psTransform->padfGeoLocX[iX + iY * nXSize]
               == psTransform->dfNoDataX )
               continue;

           i = iX + iY * nXSize;

           iBMX = (int) ((psTransform->padfGeoLocX[i] - dfMinX) / dfPixelSize);
           iBMY = (int) ((dfMaxY - psTransform->padfGeoLocY[i]) / dfPixelSize);

           if( iBMX < 0 || iBMY < 0 || iBMX >= nBMXSize || iBMY >= nBMYSize )
               continue;

           psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] =
               (float)(iX * psTransform->dfPIXEL_STEP + psTransform->dfPIXEL_OFFSET);
           psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] =
               (float)(iY * psTransform->dfLINE_STEP + psTransform->dfLINE_OFFSET);

          // Mark genuinely valid with maximum value
           pabyValidFlag[iBMX + iBMY * nBMXSize] = iMaxIter+1;

       }
    }





    int iIter;

    int iNumValid, iExpectedValid;

    for( iIter = 0; iIter < iMaxIter; iIter++ )
    {
       iNumValid = 0;
      iExpectedValid = (nBMYSize - 2) * (nBMXSize - 2);
       for( iBMY = 1; iBMY < nBMYSize-1; iBMY++ )
       {
           for( iBMX = 1; iBMX < nBMXSize-1; iBMX++ )
           {
               // if this point is already set, ignore it.
               if( pabyValidFlag[iBMX + iBMY*nBMXSize] )
             {
               iNumValid++;
                   continue;
             }

               int nCount = 0;
               double dfXSum = 0.0, dfYSum = 0.0;
             int iDoublePlusGood = iMaxIter - iIter;

               // left?
               if( (iBMX > 0) && (pabyValidFlag[iBMX-1+iBMY*nBMXSize] > iDoublePlusGood) )
               {
                   dfXSum += psTransform->pafBackMapX[iBMX-1+iBMY*nBMXSize];
                   dfYSum += psTransform->pafBackMapY[iBMX-1+iBMY*nBMXSize];
                   nCount++;
               }
               // right?
               if( (iBMX < nBMXSize-1) && (pabyValidFlag[iBMX+1+iBMY*nBMXSize] > iDoublePlusGood) )
               {
                   dfXSum += psTransform->pafBackMapX[iBMX+1+iBMY*nBMXSize];
                   dfYSum += psTransform->pafBackMapY[iBMX+1+iBMY*nBMXSize];
                   nCount++;
               }
               // top?
               if( (iBMY > 0) && (pabyValidFlag[iBMX+(iBMY-1)*nBMXSize] > iDoublePlusGood) )
               {
                   dfXSum += psTransform->pafBackMapX[iBMX+(iBMY-1)*nBMXSize];
                   dfYSum += psTransform->pafBackMapY[iBMX+(iBMY-1)*nBMXSize];
                   nCount++;
               }
               // bottom?
               if( (iBMY < nBMYSize-1) && (pabyValidFlag[iBMX+(iBMY+1)*nBMXSize] > iDoublePlusGood) )
               {
                   dfXSum += psTransform->pafBackMapX[iBMX+(iBMY+1)*nBMXSize];
                   dfYSum += psTransform->pafBackMapY[iBMX+(iBMY+1)*nBMXSize];
                   nCount++;
               }
             // top-left?
               if( (iBMX > 0) && (iBMY > 0) && (pabyValidFlag[iBMX-1+(iBMY-1)*nBMXSize] > iDoublePlusGood) )
             {
                   dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY-1)*nBMXSize];
                   dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY-1)*nBMXSize];
                   nCount++;
             }
             // top-right?
               if( (iBMX < nBMXSize-1) && (pabyValidFlag[iBMX+1+(iBMY-1)*nBMXSize] > iDoublePlusGood) )
             {
                   dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY-1)*nBMXSize];
                   dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY-1)*nBMXSize];
                   nCount++;
             }
             // bottom-left?
               if( (iBMY < nBMYSize-1) && (iBMX > 0) && (pabyValidFlag[iBMX-1+(iBMY+1)*nBMXSize] > iDoublePlusGood) )
             {
                   dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY+1)*nBMXSize];
                   dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY+1)*nBMXSize];
                   nCount++;
             }
             // bottom-right?
               if( (iBMY < nBMYSize-1) && (iBMX < nBMXSize-1) && (pabyValidFlag[iBMX+1+(iBMY+1)*nBMXSize] > iDoublePlusGood) )
             {
                   dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY+1)*nBMXSize];
                   dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY+1)*nBMXSize];
                   nCount++;
             }

               if( nCount > 0 )
               {
                   psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] = (float)(dfXSum/nCount);
                   psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] = (float)(dfYSum/nCount);
                // genuinely valid points will have value iMaxIter+1
                // On each iteration mark newly valid points with a
                // descending value so that it will not be used on the
                // current iteration only on subsequent ones.
               pabyValidFlag[iBMX+iBMY*nBMXSize] = iMaxIter - iIter;
               }
           }
       }
       if (getenv("DEBUG")) fprintf(stderr, "After iter %d there are %d / %d (%d x %d) valid\n", iIter, iNumValid, iExpectedValid, nBMXSize, nBMYSize);
       if (iNumValid == iExpectedValid)
          break;
    }

#ifdef notdef
    GDALDatasetH hBMDS = GDALCreate( GDALGetDriverByName( "GTiff" ),
                                    "backmap.tif", nBMXSize, nBMYSize, 2,
                                    GDT_Float32, NULL );
   GDALSetGeoTransform( hBMDS, psTransform->adfBackMapGeoTransform );
   GDALRasterIO( GDALGetRasterBand(hBMDS,1), GF_Write,
                 0, 0, nBMXSize, nBMYSize,
                 psTransform->pafBackMapX, nBMXSize, nBMYSize,
                 GDT_Float32, 0, 0 );
   GDALRasterIO( GDALGetRasterBand(hBMDS,2), GF_Write,
                 0, 0, nBMXSize, nBMYSize,
                 psTransform->pafBackMapY, nBMXSize, nBMYSize,
                 GDT_Float32, 0, 0 );
    GDALClose( hBMDS );
#endif

    CPLFree( pabyValidFlag );

    return TRUE;
}





#ifdef notdef



static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
                              double dfGeoX, double dfGeoY,
                              int nStartX, int nStartY,
                              double *pdfFoundX, double *pdfFoundY )

{
    double adfPathX[5000], adfPathY[5000];

    if( psTransform->padfGeoLocX == NULL )
       return FALSE;

    int nXSize = psTransform->nGeoLocXSize;
    int nYSize = psTransform->nGeoLocYSize;
    int nStepCount = 0;

    // Start in center if we don't have any provided info.
    if( nStartX < 0 || nStartY < 0
       || nStartX >= nXSize || nStartY >= nYSize )
    {
       nStartX = nXSize / 2;
       nStartY = nYSize / 2;
    }

    nStartX = MIN(nStartX,nXSize-2);
    nStartY = MIN(nStartY,nYSize-2);

    int iX = nStartX, iY = nStartY;
    int iLastX = -1, iLastY = -1;
    int iSecondLastX = -1, iSecondLastY = -1;

    while( nStepCount < MAX(nXSize,nYSize) )
    {
       int iXNext = -1, iYNext = -1;
       double dfDeltaXRight, dfDeltaYRight, dfDeltaXDown, dfDeltaYDown;

       double *padfThisX = psTransform->padfGeoLocX + iX + iY * nXSize;
       double *padfThisY = psTransform->padfGeoLocY + iX + iY * nXSize;

       double dfDeltaX = dfGeoX - *padfThisX;
       double dfDeltaY = dfGeoY - *padfThisY;

       if( iX == nXSize-1 )
       {
           dfDeltaXRight = *(padfThisX) - *(padfThisX-1);
           dfDeltaYRight = *(padfThisY) - *(padfThisY-1);
       }
       else
       {
           dfDeltaXRight = *(padfThisX+1) - *padfThisX;
           dfDeltaYRight = *(padfThisY+1) - *padfThisY;
       }

       if( iY == nYSize - 1 )
       {
           dfDeltaXDown = *(padfThisX) - *(padfThisX-nXSize);
           dfDeltaYDown = *(padfThisY) - *(padfThisY-nXSize);
       }
       else
       {
           dfDeltaXDown = *(padfThisX+nXSize) - *padfThisX;
           dfDeltaYDown = *(padfThisY+nXSize) - *padfThisY;
       }

       double dfRightProjection =
           (dfDeltaXRight * dfDeltaX + dfDeltaYRight * dfDeltaY)
           / (dfDeltaXRight*dfDeltaXRight + dfDeltaYRight*dfDeltaYRight);

       double dfDownProjection =
           (dfDeltaXDown * dfDeltaX + dfDeltaYDown * dfDeltaY)
           / (dfDeltaXDown*dfDeltaXDown + dfDeltaYDown*dfDeltaYDown);

       // Are we in our target cell?
       if( dfRightProjection >= 0.0 && dfRightProjection < 1.0
           && dfDownProjection >= 0.0 && dfDownProjection < 1.0 )
       {
           *pdfFoundX = iX + dfRightProjection;
           *pdfFoundY = iY + dfDownProjection;

           return TRUE;
       }
           
       if( ABS(dfRightProjection) > ABS(dfDownProjection) )
       {
           // Do we want to move right?
           if( dfRightProjection > 1.0 && iX < nXSize-1 )
           {
               iXNext = iX + MAX(1,(int)(dfRightProjection - nStepCount)/2);
               iYNext = iY;
           }
           
           // Do we want to move left?
           else if( dfRightProjection < 0.0 && iX > 0 )
           {
               iXNext = iX - MAX(1,(int)(ABS(dfRightProjection) - nStepCount)/2);
               iYNext = iY;
           }
           
           // Do we want to move down.
           else if( dfDownProjection > 1.0 && iY < nYSize-1 )
           {
               iXNext = iX;
               iYNext = iY + MAX(1,(int)(dfDownProjection - nStepCount)/2);
           }
           
           // Do we want to move up?
           else if( dfDownProjection < 0.0 && iY > 0 )
           {
               iXNext = iX;
               iYNext = iY - MAX(1,(int)(ABS(dfDownProjection) - nStepCount)/2);
           }
           
           // We aren't there, and we have no where to go
           else
           {
               return FALSE;
           }
       }
       else
       {
           // Do we want to move down.
           if( dfDownProjection > 1.0 && iY < nYSize-1 )
           {
               iXNext = iX;
               iYNext = iY + MAX(1,(int)(dfDownProjection - nStepCount)/2);
           }
           
           // Do we want to move up?
           else if( dfDownProjection < 0.0 && iY > 0 )
           {
               iXNext = iX;
               iYNext = iY - MAX(1,(int)(ABS(dfDownProjection) - nStepCount)/2);
           }
           
           // Do we want to move right?
           else if( dfRightProjection > 1.0 && iX < nXSize-1 )
           {
               iXNext = iX + MAX(1,(int)(dfRightProjection - nStepCount)/2);
               iYNext = iY;
           }
           
           // Do we want to move left?
           else if( dfRightProjection < 0.0 && iX > 0 )
           {
               iXNext = iX - MAX(1,(int)(ABS(dfRightProjection) - nStepCount)/2);
               iYNext = iY;
           }
           
           // We aren't there, and we have no where to go
           else
           {
               return FALSE;
           }
       }
               adfPathX[nStepCount] = iX;
       adfPathY[nStepCount] = iY;

       nStepCount++;
       iX = MAX(0,MIN(iXNext,nXSize-1));
       iY = MAX(0,MIN(iYNext,nYSize-1));

       if( iX == iSecondLastX && iY == iSecondLastY )
       {
           // Are we *near* our target cell?
           if( dfRightProjection >= -1.0 && dfRightProjection < 2.0
               && dfDownProjection >= -1.0 && dfDownProjection < 2.0 )
           {
               *pdfFoundX = iX + dfRightProjection;
               *pdfFoundY = iY + dfDownProjection;
               
               return TRUE;
           }

#ifdef SHAPE_DEBUG
           if( hSHP != NULL )
           {
               SHPObject *hObj;
               
               hObj = SHPCreateSimpleObject( SHPT_ARC, nStepCount,
                                             adfPathX, adfPathY, NULL );
               SHPWriteObject( hSHP, -1, hObj );
               SHPDestroyObject( hObj );
               
               int iShape = DBFGetRecordCount( hDBF );
               DBFWriteDoubleAttribute( hDBF, iShape, 0, dfGeoX );
               DBFWriteDoubleAttribute( hDBF, iShape, 1, dfGeoY );
           }
#endif            
           //CPLDebug( "GeoL", "Looping at step (%d) on search for %g,%g.",
           //         nStepCount, dfGeoX, dfGeoY );
           return FALSE;
       }

       iSecondLastX = iLastX;
       iSecondLastY = iLastY;

       iLastX = iX;
       iLastY = iY;

    }

    //CPLDebug( "GeoL", "Exceeded step count max (%d) on search for %g,%g.",
   //         MAX(nXSize,nYSize),
   //         dfGeoX, dfGeoY );
   
#ifdef SHAPE_DEBUG
    if( hSHP != NULL )
    {
       SHPObject *hObj;

       hObj = SHPCreateSimpleObject( SHPT_ARC, nStepCount,
                                     adfPathX, adfPathY, NULL );
       SHPWriteObject( hSHP, -1, hObj );
       SHPDestroyObject( hObj );

       int iShape = DBFGetRecordCount( hDBF );
       DBFWriteDoubleAttribute( hDBF, iShape, 0, dfGeoX );
       DBFWriteDoubleAttribute( hDBF, iShape, 1, dfGeoY );
    }
#endif
             
    return FALSE;
}
#endif







void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
                                  char **papszGeolocationInfo,
                                  int bReversed )

{
   GDALGeoLocTransformInfo *psTransform;

    if( CSLFetchNameValue(papszGeolocationInfo,"PIXEL_OFFSET") == NULL
       || CSLFetchNameValue(papszGeolocationInfo,"LINE_OFFSET") == NULL
       || CSLFetchNameValue(papszGeolocationInfo,"PIXEL_STEP") == NULL
       || CSLFetchNameValue(papszGeolocationInfo,"LINE_STEP") == NULL
       || CSLFetchNameValue(papszGeolocationInfo,"X_BAND") == NULL
       || CSLFetchNameValue(papszGeolocationInfo,"Y_BAND") == NULL )
    {
       CPLError( CE_Failure, CPLE_AppDefined,
                 "Missing some geolocation fields in GDALCreateGeoLocTransformer()" );
       return NULL;
    }




    psTransform = (GDALGeoLocTransformInfo *)
       CPLCalloc(sizeof(GDALGeoLocTransformInfo),1);

   psTransform->bReversed = bReversed;

    strcpy( psTransform->sTI.szSignature, "GTI" );
   psTransform->sTI.pszClassName = "GDALGeoLocTransformer";
   psTransform->sTI.pfnTransform = GDALGeoLocTransform;
   psTransform->sTI.pfnCleanup = GDALDestroyGeoLocTransformer;
   psTransform->sTI.pfnSerialize = GDALSerializeGeoLocTransformer;
   psTransform->papszGeolocationInfo = CSLDuplicate( papszGeolocationInfo );




   psTransform->dfPIXEL_OFFSET = atof(CSLFetchNameValue( papszGeolocationInfo,
                                                         "PIXEL_OFFSET" ));
   psTransform->dfLINE_OFFSET = atof(CSLFetchNameValue( papszGeolocationInfo,
                                                        "LINE_OFFSET" ));
   psTransform->dfPIXEL_STEP = atof(CSLFetchNameValue( papszGeolocationInfo,
                                                       "PIXEL_STEP" ));
   psTransform->dfLINE_STEP = atof(CSLFetchNameValue( papszGeolocationInfo,
                                                      "LINE_STEP" ));




    const char *pszDSName = CSLFetchNameValue( papszGeolocationInfo,
                                              "X_DATASET" );
    if( pszDSName != NULL )
    {
       psTransform->hDS_X = GDALOpenShared( pszDSName, GA_ReadOnly );
    }
    else
    {
       psTransform->hDS_X = hBaseDS;
       GDALReferenceDataset( psTransform->hDS_X );
       psTransform->papszGeolocationInfo =
           CSLSetNameValue( psTransform->papszGeolocationInfo,
                            "X_DATASET",
                            GDALGetDescription( hBaseDS ) );
    }

    pszDSName = CSLFetchNameValue( papszGeolocationInfo, "Y_DATASET" );
    if( pszDSName != NULL )
    {
       psTransform->hDS_Y = GDALOpenShared( pszDSName, GA_ReadOnly );
    }
    else
    {
       psTransform->hDS_Y = hBaseDS;
       GDALReferenceDataset( psTransform->hDS_Y );
       psTransform->papszGeolocationInfo =
           CSLSetNameValue( psTransform->papszGeolocationInfo,
                            "Y_DATASET",
                            GDALGetDescription( hBaseDS ) );
    }




    int nBand;

    nBand = MAX(1,atoi(CSLFetchNameValue( papszGeolocationInfo, "X_BAND" )));
   psTransform->hBand_X = GDALGetRasterBand( psTransform->hDS_X, nBand );

    nBand = MAX(1,atoi(CSLFetchNameValue( papszGeolocationInfo, "Y_BAND" )));
   psTransform->hBand_Y = GDALGetRasterBand( psTransform->hDS_Y, nBand );




    if( !GeoLocLoadFullData( psTransform )
       || !GeoLocGenerateBackMap( psTransform ) )
    {
       GDALDestroyGeoLocTransformer( psTransform );
       return NULL;
    }

    return psTransform;
}





void GDALDestroyGeoLocTransformer( void *pTransformAlg )

{
   GDALGeoLocTransformInfo *psTransform =
       (GDALGeoLocTransformInfo *) pTransformAlg;

    CPLFree( psTransform->pafBackMapX );
    CPLFree( psTransform->pafBackMapY );
    CSLDestroy( psTransform->papszGeolocationInfo );
    CPLFree( psTransform->padfGeoLocX );
    CPLFree( psTransform->padfGeoLocY );
            
    if( psTransform->hDS_X != NULL
       && GDALDereferenceDataset( psTransform->hDS_X ) == 0 )
           GDALClose( psTransform->hDS_X );

    if( psTransform->hDS_Y != NULL
       && GDALDereferenceDataset( psTransform->hDS_Y ) == 0 )
           GDALClose( psTransform->hDS_Y );

    CPLFree( pTransformAlg );
}





int GDALGeoLocTransform( void *pTransformArg, int bDstToSrc,
                        int nPointCount,
                        double *padfX, double *padfY, double *padfZ,
                        int *panSuccess )

{
   GDALGeoLocTransformInfo *psTransform =
       (GDALGeoLocTransformInfo *) pTransformArg;

    if( psTransform->bReversed )
       bDstToSrc = !bDstToSrc;




    if( !bDstToSrc )
    {
       int i, nXSize = psTransform->nGeoLocXSize;

       for( i = 0; i < nPointCount; i++ )
       {
           if( !panSuccess[i] )
               continue;

           if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
           {
               panSuccess[i] = FALSE;
               continue;
           }

           double dfGeoLocPixel = (padfX[i] - psTransform->dfPIXEL_OFFSET)
               / psTransform->dfPIXEL_STEP;
           double dfGeoLocLine = (padfY[i] - psTransform->dfLINE_OFFSET)
               / psTransform->dfLINE_STEP;

           int iX, iY;

           iX = MAX(0,(int) dfGeoLocPixel);
           iX = MIN(iX,psTransform->nGeoLocXSize-2);
           iY = MAX(0,(int) dfGeoLocLine);
           iY = MIN(iY,psTransform->nGeoLocYSize-2);

           double *padfGLX = psTransform->padfGeoLocX + iX + iY * nXSize;
           double *padfGLY = psTransform->padfGeoLocY + iX + iY * nXSize;

           // This assumes infinite extension beyond borders of available
           // data based on closest grid square.

           padfX[i] = padfGLX[0]
               + (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0])
               + (dfGeoLocLine -iY) * (padfGLX[nXSize] - padfGLX[0]);
           padfY[i] = padfGLY[0]
               + (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0])
               + (dfGeoLocLine -iY) * (padfGLY[nXSize] - padfGLY[0]);

           panSuccess[i] = TRUE;
       }
    }




    else
    {
       int i;

       for( i = 0; i < nPointCount; i++ )
       {
           if( !panSuccess[i] )
               continue;

           if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
           {
               panSuccess[i] = FALSE;
               continue;
           }

           int iBMX, iBMY;

           iBMX = (int) ((padfX[i] - psTransform->adfBackMapGeoTransform[0])
                         / psTransform->adfBackMapGeoTransform[1]);
           iBMY = (int) ((padfY[i] - psTransform->adfBackMapGeoTransform[3])
                         / psTransform->adfBackMapGeoTransform[5]);

           int iBM = iBMX + iBMY * psTransform->nBackMapWidth;

           if( iBMX < 0 || iBMY < 0
               || iBMX >= psTransform->nBackMapWidth
               || iBMY >= psTransform->nBackMapHeight
               || psTransform->pafBackMapX[iBM] < 0 )
           {
               panSuccess[i] = FALSE;
               padfX[i] = HUGE_VAL;
               padfY[i] = HUGE_VAL;
               continue;
           }

           padfX[i] = psTransform->pafBackMapX[iBM];
           padfY[i] = psTransform->pafBackMapY[iBM];
           panSuccess[i] = TRUE;
       }
    }




#ifdef notdef
    else
    {
       int i;
       int nStartX = -1, nStartY = -1;

#ifdef SHAPE_DEBUG
       hSHP = SHPCreate( "tracks.shp", SHPT_ARC );
       hDBF = DBFCreate( "tracks.dbf" );
       DBFAddField( hDBF, "GEOX", FTDouble, 10, 4 );
       DBFAddField( hDBF, "GEOY", FTDouble, 10, 4 );
#endif
       for( i = 0; i < nPointCount; i++ )
       {
           double dfGeoLocX, dfGeoLocY;

           if( !panSuccess[i] )
               continue;

           if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
           {
               panSuccess[i] = FALSE;
               continue;
           }

           if( !FindGeoLocPosition( psTransform, padfX[i], padfY[i],
                                    -1, -1, &dfGeoLocX, &dfGeoLocY ) )
           {
               padfX[i] = HUGE_VAL;
               padfY[i] = HUGE_VAL;

               panSuccess[i] = FALSE;
               continue;
           }
           nStartX = (int) dfGeoLocX;
           nStartY = (int) dfGeoLocY;

           padfX[i] = dfGeoLocX * psTransform->dfPIXEL_STEP
               + psTransform->dfPIXEL_OFFSET;
           padfY[i] = dfGeoLocY * psTransform->dfLINE_STEP
               + psTransform->dfLINE_OFFSET;

           panSuccess[i] = TRUE;
       }

#ifdef SHAPE_DEBUG
       if( hSHP != NULL )
       {
           DBFClose( hDBF );
           hDBF = NULL;
           
           SHPClose( hSHP );
           hSHP = NULL;
       }
#endif
    }
#endif

    return TRUE;
}





CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg )

{
   VALIDATE_POINTER1( pTransformArg, "GDALSerializeGeoLocTransformer", NULL );

    CPLXMLNode *psTree;
   GDALGeoLocTransformInfo *psInfo =
       (GDALGeoLocTransformInfo *)(pTransformArg);

    psTree = CPLCreateXMLNode( NULL, CXT_Element, "GeoLocTransformer" );




   CPLCreateXMLElementAndValue(
       psTree, "Reversed",
       CPLString().Printf( "%d", psInfo->bReversed ) );
                                



    char **papszMD = psInfo->papszGeolocationInfo;
    CPLXMLNode *psMD= CPLCreateXMLNode( psTree, CXT_Element,
                                       "Metadata" );

    for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
    {
       const char *pszRawValue;
       char *pszKey;
       CPLXMLNode *psMDI;
               
       pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
               
       psMDI = CPLCreateXMLNode( psMD, CXT_Element, "MDI" );
       CPLSetXMLValue( psMDI, "#key", pszKey );
       CPLCreateXMLNode( psMDI, CXT_Text, pszRawValue );
               
       CPLFree( pszKey );
    }

    return psTree;
}





void *GDALDeserializeGeoLocTransformer( CPLXMLNode *psTree )

{
    void *pResult;
    int bReversed;
    char **papszMD = NULL;
    CPLXMLNode *psMDI, *psMetadata;




    psMetadata = CPLGetXMLNode( psTree, "Metadata" );

    if( psMetadata->eType != CXT_Element
       || !EQUAL(psMetadata->pszValue,"Metadata") )
       return NULL;
   
    for( psMDI = psMetadata->psChild; psMDI != NULL;
        psMDI = psMDI->psNext )
    {
       if( !EQUAL(psMDI->pszValue,"MDI")
           || psMDI->eType != CXT_Element
           || psMDI->psChild == NULL
           || psMDI->psChild->psNext == NULL
           || psMDI->psChild->eType != CXT_Attribute
           || psMDI->psChild->psChild == NULL )
           continue;
       
       papszMD =
           CSLSetNameValue( papszMD,
                            psMDI->psChild->psChild->pszValue,
                            psMDI->psChild->psNext->pszValue );
    }




    bReversed = atoi(CPLGetXMLValue(psTree,"Reversed","0"));




    pResult = GDALCreateGeoLocTransformer( NULL, papszMD, bReversed );
   



    CSLDestroy( papszMD );

    return pResult;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zou_ys88

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值