mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-18 06:06:01 -06:00
1280 lines
47 KiB
C++
1280 lines
47 KiB
C++
/******************************************************************************
|
|
* $Id: gdalgeoloc.cpp 29207 2015-05-18 17:23:45Z mloskot $
|
|
*
|
|
* Project: GDAL
|
|
* Purpose: Implements Geolocation array based transformer.
|
|
* Author: Frank Warmerdam, warmerdam@pobox.com
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 2006, Frank Warmerdam <warmerdam@pobox.com>
|
|
* Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#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 29207 2015-05-18 17:23:45Z mloskot $");
|
|
|
|
CPL_C_START
|
|
CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg );
|
|
void *GDALDeserializeGeoLocTransformer( CPLXMLNode *psTree );
|
|
CPL_C_END
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* GDALGeoLocTransformer */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
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;
|
|
|
|
int bHasNoData;
|
|
double dfNoDataX;
|
|
|
|
// geolocation <-> base image mapping.
|
|
double dfPIXEL_OFFSET;
|
|
double dfPIXEL_STEP;
|
|
double dfLINE_OFFSET;
|
|
double dfLINE_STEP;
|
|
|
|
char ** papszGeolocationInfo;
|
|
|
|
} GDALGeoLocTransformInfo;
|
|
|
|
/************************************************************************/
|
|
/* GeoLocLoadFullData() */
|
|
/************************************************************************/
|
|
|
|
static int GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )
|
|
|
|
{
|
|
int nXSize, nYSize;
|
|
|
|
int nXSize_XBand = GDALGetRasterXSize( psTransform->hDS_X );
|
|
int nYSize_XBand = GDALGetRasterYSize( psTransform->hDS_X );
|
|
int nXSize_YBand = GDALGetRasterXSize( psTransform->hDS_Y );
|
|
int nYSize_YBand = GDALGetRasterYSize( psTransform->hDS_Y );
|
|
if (nYSize_XBand == 1 && nYSize_YBand == 1)
|
|
{
|
|
nXSize = nXSize_XBand;
|
|
nYSize = nXSize_YBand;
|
|
}
|
|
else
|
|
{
|
|
nXSize = nXSize_XBand;
|
|
nYSize = nYSize_XBand;
|
|
}
|
|
|
|
psTransform->nGeoLocXSize = nXSize;
|
|
psTransform->nGeoLocYSize = nYSize;
|
|
|
|
psTransform->padfGeoLocY = (double *)
|
|
VSIMalloc3(sizeof(double), nXSize, nYSize);
|
|
psTransform->padfGeoLocX = (double *)
|
|
VSIMalloc3(sizeof(double), nXSize, nYSize);
|
|
|
|
if( psTransform->padfGeoLocX == NULL ||
|
|
psTransform->padfGeoLocY == NULL )
|
|
{
|
|
CPLError(CE_Failure, CPLE_OutOfMemory,
|
|
"GeoLocLoadFullData : Out of memory");
|
|
return FALSE;
|
|
}
|
|
|
|
if (nYSize_XBand == 1 && nYSize_YBand == 1)
|
|
{
|
|
/* Case of regular grid */
|
|
/* The XBAND contains the x coordinates for all lines */
|
|
/* The YBAND contains the y coordinates for all columns */
|
|
|
|
double* padfTempX = (double*)VSIMalloc2(nXSize, sizeof(double));
|
|
double* padfTempY = (double*)VSIMalloc2(nYSize, sizeof(double));
|
|
if (padfTempX == NULL || padfTempY == NULL)
|
|
{
|
|
CPLFree(padfTempX);
|
|
CPLFree(padfTempY);
|
|
CPLError(CE_Failure, CPLE_OutOfMemory,
|
|
"GeoLocLoadFullData : Out of memory");
|
|
return FALSE;
|
|
}
|
|
|
|
CPLErr eErr = CE_None;
|
|
|
|
eErr = GDALRasterIO( psTransform->hBand_X, GF_Read,
|
|
0, 0, nXSize, 1,
|
|
padfTempX, nXSize, 1,
|
|
GDT_Float64, 0, 0 );
|
|
|
|
int i,j;
|
|
for(j=0;j<nYSize;j++)
|
|
{
|
|
memcpy( psTransform->padfGeoLocX + j * nXSize,
|
|
padfTempX,
|
|
nXSize * sizeof(double) );
|
|
}
|
|
|
|
if (eErr == CE_None)
|
|
{
|
|
eErr = GDALRasterIO( psTransform->hBand_Y, GF_Read,
|
|
0, 0, nYSize, 1,
|
|
padfTempY, nYSize, 1,
|
|
GDT_Float64, 0, 0 );
|
|
|
|
for(j=0;j<nYSize;j++)
|
|
{
|
|
for(i=0;i<nXSize;i++)
|
|
{
|
|
psTransform->padfGeoLocY[j * nXSize + i] = padfTempY[j];
|
|
}
|
|
}
|
|
}
|
|
|
|
CPLFree(padfTempX);
|
|
CPLFree(padfTempY);
|
|
|
|
if (eErr != CE_None)
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
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,
|
|
&(psTransform->bHasNoData) );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GeoLocGenerateBackMap() */
|
|
/************************************************************************/
|
|
|
|
static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
|
|
|
|
{
|
|
int nXSize = psTransform->nGeoLocXSize;
|
|
int nYSize = psTransform->nGeoLocYSize;
|
|
int nMaxIter = 3;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Scan forward map for lat/long extents. */
|
|
/* -------------------------------------------------------------------- */
|
|
double dfMinX=0, dfMaxX=0, dfMinY=0, dfMaxY=0;
|
|
int i, bInit = FALSE;
|
|
|
|
for( i = nXSize * nYSize - 1; i >= 0; i-- )
|
|
{
|
|
if( !psTransform->bHasNoData ||
|
|
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];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Decide on resolution for backmap. We aim for slightly */
|
|
/* higher resolution than the source but we can't easily */
|
|
/* establish how much dead space there is in the backmap, so it */
|
|
/* is approximate. */
|
|
/* -------------------------------------------------------------------- */
|
|
double dfTargetPixels = (nXSize * nYSize * 1.3);
|
|
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);
|
|
|
|
if (nBMXSize > INT_MAX / nBMYSize)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "Int overflow : %d x %d",
|
|
nBMXSize, nBMYSize);
|
|
return FALSE;
|
|
}
|
|
|
|
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;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Allocate backmap, and initialize to nodata value (-1.0). */
|
|
/* -------------------------------------------------------------------- */
|
|
GByte *pabyValidFlag;
|
|
|
|
pabyValidFlag = (GByte *)
|
|
VSICalloc(nBMXSize, nBMYSize);
|
|
|
|
psTransform->pafBackMapX = (float *)
|
|
VSIMalloc3(nBMXSize, nBMYSize, sizeof(float));
|
|
psTransform->pafBackMapY = (float *)
|
|
VSIMalloc3(nBMXSize, nBMYSize, sizeof(float));
|
|
|
|
if( pabyValidFlag == NULL ||
|
|
psTransform->pafBackMapX == NULL ||
|
|
psTransform->pafBackMapY == NULL )
|
|
{
|
|
CPLError( CE_Failure, CPLE_OutOfMemory,
|
|
"Unable to allocate %dx%d back-map for geolocation array transformer.",
|
|
nBMXSize, nBMYSize );
|
|
CPLFree( pabyValidFlag );
|
|
return FALSE;
|
|
}
|
|
|
|
for( i = nBMXSize * nBMYSize - 1; i >= 0; i-- )
|
|
{
|
|
psTransform->pafBackMapX[i] = -1.0;
|
|
psTransform->pafBackMapY[i] = -1.0;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Run through the whole geoloc array forward projecting and */
|
|
/* pushing into the backmap. */
|
|
/* Initialise to the nMaxIter+1 value so we can spot genuinely */
|
|
/* valid pixels in the hole-filling loop. */
|
|
/* -------------------------------------------------------------------- */
|
|
int iBMX, iBMY;
|
|
int iX, iY;
|
|
|
|
for( iY = 0; iY < nYSize; iY++ )
|
|
{
|
|
for( iX = 0; iX < nXSize; iX++ )
|
|
{
|
|
if( psTransform->bHasNoData &&
|
|
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);
|
|
|
|
pabyValidFlag[iBMX + iBMY * nBMXSize] = (GByte) (nMaxIter+1);
|
|
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Now, loop over the backmap trying to fill in holes with */
|
|
/* nearby values. */
|
|
/* -------------------------------------------------------------------- */
|
|
int iIter;
|
|
int nNumValid;
|
|
|
|
for( iIter = 0; iIter < nMaxIter; iIter++ )
|
|
{
|
|
nNumValid = 0;
|
|
for( iBMY = 0; iBMY < nBMYSize; iBMY++ )
|
|
{
|
|
for( iBMX = 0; iBMX < nBMXSize; iBMX++ )
|
|
{
|
|
// if this point is already set, ignore it.
|
|
if( pabyValidFlag[iBMX + iBMY*nBMXSize] )
|
|
{
|
|
nNumValid++;
|
|
continue;
|
|
}
|
|
|
|
int nCount = 0;
|
|
double dfXSum = 0.0, dfYSum = 0.0;
|
|
int nMarkedAsGood = nMaxIter - iIter;
|
|
|
|
// left?
|
|
if( iBMX > 0 &&
|
|
pabyValidFlag[iBMX-1+iBMY*nBMXSize] > nMarkedAsGood )
|
|
{
|
|
dfXSum += psTransform->pafBackMapX[iBMX-1+iBMY*nBMXSize];
|
|
dfYSum += psTransform->pafBackMapY[iBMX-1+iBMY*nBMXSize];
|
|
nCount++;
|
|
}
|
|
// right?
|
|
if( iBMX + 1 < nBMXSize &&
|
|
pabyValidFlag[iBMX+1+iBMY*nBMXSize] > nMarkedAsGood )
|
|
{
|
|
dfXSum += psTransform->pafBackMapX[iBMX+1+iBMY*nBMXSize];
|
|
dfYSum += psTransform->pafBackMapY[iBMX+1+iBMY*nBMXSize];
|
|
nCount++;
|
|
}
|
|
// top?
|
|
if( iBMY > 0 &&
|
|
pabyValidFlag[iBMX+(iBMY-1)*nBMXSize] > nMarkedAsGood )
|
|
{
|
|
dfXSum += psTransform->pafBackMapX[iBMX+(iBMY-1)*nBMXSize];
|
|
dfYSum += psTransform->pafBackMapY[iBMX+(iBMY-1)*nBMXSize];
|
|
nCount++;
|
|
}
|
|
// bottom?
|
|
if( iBMY + 1 < nBMYSize &&
|
|
pabyValidFlag[iBMX+(iBMY+1)*nBMXSize] > nMarkedAsGood )
|
|
{
|
|
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] > nMarkedAsGood )
|
|
{
|
|
dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY-1)*nBMXSize];
|
|
dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY-1)*nBMXSize];
|
|
nCount++;
|
|
}
|
|
// top-right?
|
|
if( iBMX + 1 < nBMXSize && iBMY > 0 &&
|
|
pabyValidFlag[iBMX+1+(iBMY-1)*nBMXSize] > nMarkedAsGood )
|
|
{
|
|
dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY-1)*nBMXSize];
|
|
dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY-1)*nBMXSize];
|
|
nCount++;
|
|
}
|
|
// bottom-left?
|
|
if( iBMX > 0 && iBMY + 1 < nBMYSize &&
|
|
pabyValidFlag[iBMX-1+(iBMY+1)*nBMXSize] > nMarkedAsGood )
|
|
{
|
|
dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY+1)*nBMXSize];
|
|
dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY+1)*nBMXSize];
|
|
nCount++;
|
|
}
|
|
// bottom-right?
|
|
if( iBMX + 1 < nBMXSize && iBMY + 1 < nBMYSize &&
|
|
pabyValidFlag[iBMX+1+(iBMY+1)*nBMXSize] > nMarkedAsGood )
|
|
{
|
|
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] = (GByte) (nMaxIter - iIter);
|
|
}
|
|
}
|
|
}
|
|
if (nNumValid == nBMXSize * nBMYSize)
|
|
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;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* FindGeoLocPosition() */
|
|
/************************************************************************/
|
|
|
|
#ifdef notdef
|
|
|
|
/*
|
|
This searching approach has been abandoned because it is too sensitive
|
|
to discontinuities in the data. Left in case it might be revived in
|
|
the future.
|
|
*/
|
|
|
|
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 /* def notdef */
|
|
|
|
|
|
/************************************************************************/
|
|
/* GDALGeoLocRescale() */
|
|
/************************************************************************/
|
|
|
|
static void GDALGeoLocRescale(char**& papszMD, const char* pszItem,
|
|
double dfRatio, double dfDefaultVal)
|
|
{
|
|
double dfVal = CPLAtofM(CSLFetchNameValueDef(papszMD, pszItem,
|
|
CPLSPrintf("%.18g", dfDefaultVal)));
|
|
dfVal *= dfRatio;
|
|
papszMD = CSLSetNameValue(papszMD, pszItem, CPLSPrintf("%.18g", dfVal));
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALCreateSimilarGeoLocTransformer() */
|
|
/************************************************************************/
|
|
|
|
static
|
|
void* GDALCreateSimilarGeoLocTransformer( void *hTransformArg, double dfRatioX, double dfRatioY )
|
|
{
|
|
VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarGeoLocTransformer", NULL );
|
|
|
|
GDALGeoLocTransformInfo *psInfo = (GDALGeoLocTransformInfo *) hTransformArg;
|
|
|
|
char** papszGeolocationInfo = CSLDuplicate(psInfo->papszGeolocationInfo);
|
|
|
|
if( dfRatioX != 1.0 || dfRatioY != 1.0 )
|
|
{
|
|
GDALGeoLocRescale(papszGeolocationInfo, "PIXEL_OFFSET", dfRatioX, 0.0);
|
|
GDALGeoLocRescale(papszGeolocationInfo, "LINE_OFFSET", dfRatioY, 0.0);
|
|
GDALGeoLocRescale(papszGeolocationInfo, "PIXEL_STEP", 1.0 / dfRatioX, 1.0);
|
|
GDALGeoLocRescale(papszGeolocationInfo, "LINE_STEP", 1.0 / dfRatioY, 1.0);
|
|
}
|
|
|
|
psInfo = (GDALGeoLocTransformInfo*) GDALCreateGeoLocTransformer(
|
|
NULL, papszGeolocationInfo, psInfo->bReversed );
|
|
|
|
CSLDestroy(papszGeolocationInfo);
|
|
|
|
return psInfo;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALCreateGeoLocTransformer() */
|
|
/************************************************************************/
|
|
|
|
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;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Initialize core info. */
|
|
/* -------------------------------------------------------------------- */
|
|
psTransform = (GDALGeoLocTransformInfo *)
|
|
CPLCalloc(sizeof(GDALGeoLocTransformInfo),1);
|
|
|
|
psTransform->bReversed = bReversed;
|
|
|
|
memcpy( psTransform->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) );
|
|
psTransform->sTI.pszClassName = "GDALGeoLocTransformer";
|
|
psTransform->sTI.pfnTransform = GDALGeoLocTransform;
|
|
psTransform->sTI.pfnCleanup = GDALDestroyGeoLocTransformer;
|
|
psTransform->sTI.pfnSerialize = GDALSerializeGeoLocTransformer;
|
|
psTransform->sTI.pfnCreateSimilar = GDALCreateSimilarGeoLocTransformer;
|
|
|
|
psTransform->papszGeolocationInfo = CSLDuplicate( papszGeolocationInfo );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Pull geolocation info from the options/metadata. */
|
|
/* -------------------------------------------------------------------- */
|
|
psTransform->dfPIXEL_OFFSET = CPLAtof(CSLFetchNameValue( papszGeolocationInfo,
|
|
"PIXEL_OFFSET" ));
|
|
psTransform->dfLINE_OFFSET = CPLAtof(CSLFetchNameValue( papszGeolocationInfo,
|
|
"LINE_OFFSET" ));
|
|
psTransform->dfPIXEL_STEP = CPLAtof(CSLFetchNameValue( papszGeolocationInfo,
|
|
"PIXEL_STEP" ));
|
|
psTransform->dfLINE_STEP = CPLAtof(CSLFetchNameValue( papszGeolocationInfo,
|
|
"LINE_STEP" ));
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Establish access to geolocation dataset(s). */
|
|
/* -------------------------------------------------------------------- */
|
|
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 ) );
|
|
}
|
|
|
|
if (psTransform->hDS_X == NULL ||
|
|
psTransform->hDS_Y == NULL)
|
|
{
|
|
GDALDestroyGeoLocTransformer( psTransform );
|
|
return NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Get the band handles. */
|
|
/* -------------------------------------------------------------------- */
|
|
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 (psTransform->hBand_X == NULL ||
|
|
psTransform->hBand_Y == NULL)
|
|
{
|
|
GDALDestroyGeoLocTransformer( psTransform );
|
|
return NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Check that X and Y bands have the same dimensions */
|
|
/* -------------------------------------------------------------------- */
|
|
int nXSize_XBand = GDALGetRasterXSize( psTransform->hDS_X );
|
|
int nYSize_XBand = GDALGetRasterYSize( psTransform->hDS_X );
|
|
int nXSize_YBand = GDALGetRasterXSize( psTransform->hDS_Y );
|
|
int nYSize_YBand = GDALGetRasterYSize( psTransform->hDS_Y );
|
|
if (nYSize_XBand == 1 || nYSize_YBand == 1)
|
|
{
|
|
if (nYSize_XBand != 1 || nYSize_YBand != 1)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"X_BAND and Y_BAND should have both nYSize == 1");
|
|
GDALDestroyGeoLocTransformer( psTransform );
|
|
return NULL;
|
|
}
|
|
}
|
|
else if (nXSize_XBand != nXSize_YBand ||
|
|
nYSize_XBand != nYSize_YBand )
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"X_BAND and Y_BAND do not have the same dimensions");
|
|
GDALDestroyGeoLocTransformer( psTransform );
|
|
return NULL;
|
|
}
|
|
|
|
if (nXSize_XBand > INT_MAX / nYSize_XBand)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "Int overflow : %d x %d",
|
|
nXSize_XBand, nYSize_XBand);
|
|
GDALDestroyGeoLocTransformer( psTransform );
|
|
return NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Load the geolocation array. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( !GeoLocLoadFullData( psTransform )
|
|
|| !GeoLocGenerateBackMap( psTransform ) )
|
|
{
|
|
GDALDestroyGeoLocTransformer( psTransform );
|
|
return NULL;
|
|
}
|
|
|
|
return psTransform;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALDestroyGeoLocTransformer() */
|
|
/************************************************************************/
|
|
|
|
void GDALDestroyGeoLocTransformer( void *pTransformAlg )
|
|
|
|
{
|
|
if( pTransformAlg == NULL )
|
|
return;
|
|
|
|
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 );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALGeoLocTransform() */
|
|
/************************************************************************/
|
|
|
|
int GDALGeoLocTransform( void *pTransformArg,
|
|
int bDstToSrc,
|
|
int nPointCount,
|
|
double *padfX, double *padfY,
|
|
CPL_UNUSED double *padfZ,
|
|
int *panSuccess )
|
|
{
|
|
GDALGeoLocTransformInfo *psTransform =
|
|
(GDALGeoLocTransformInfo *) pTransformArg;
|
|
|
|
if( psTransform->bReversed )
|
|
bDstToSrc = !bDstToSrc;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Do original pixel line to target geox/geoy. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( !bDstToSrc )
|
|
{
|
|
int i, nXSize = psTransform->nGeoLocXSize;
|
|
|
|
for( i = 0; i < nPointCount; i++ )
|
|
{
|
|
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-1);
|
|
iY = MAX(0,(int) dfGeoLocLine);
|
|
iY = MIN(iY,psTransform->nGeoLocYSize-1);
|
|
|
|
double *padfGLX = psTransform->padfGeoLocX + iX + iY * nXSize;
|
|
double *padfGLY = psTransform->padfGeoLocY + iX + iY * nXSize;
|
|
|
|
if( psTransform->bHasNoData &&
|
|
padfGLX[0] == psTransform->dfNoDataX )
|
|
{
|
|
panSuccess[i] = FALSE;
|
|
padfX[i] = HUGE_VAL;
|
|
padfY[i] = HUGE_VAL;
|
|
continue;
|
|
}
|
|
|
|
// This assumes infinite extension beyond borders of available
|
|
// data based on closest grid square.
|
|
|
|
if( iX + 1 < psTransform->nGeoLocXSize &&
|
|
iY + 1 < psTransform->nGeoLocYSize &&
|
|
(!psTransform->bHasNoData ||
|
|
(padfGLX[1] != psTransform->dfNoDataX &&
|
|
padfGLX[nXSize] != psTransform->dfNoDataX &&
|
|
padfGLX[nXSize + 1] != psTransform->dfNoDataX) ))
|
|
{
|
|
padfX[i] = (1 - (dfGeoLocLine -iY)) * (padfGLX[0] + (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0]))
|
|
+ (dfGeoLocLine -iY) * (padfGLX[nXSize] + (dfGeoLocPixel-iX) * (padfGLX[nXSize+1] - padfGLX[nXSize]));
|
|
padfY[i] = (1 - (dfGeoLocLine -iY)) * (padfGLY[0] + (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0]))
|
|
+ (dfGeoLocLine -iY) * (padfGLY[nXSize] + (dfGeoLocPixel-iX) * (padfGLY[nXSize+1] - padfGLY[nXSize]));
|
|
}
|
|
else if( iX + 1 < psTransform->nGeoLocXSize &&
|
|
(!psTransform->bHasNoData ||
|
|
padfGLX[1] != psTransform->dfNoDataX) )
|
|
{
|
|
padfX[i] = padfGLX[0]
|
|
+ (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0]);
|
|
padfY[i] = padfGLY[0]
|
|
+ (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0]);
|
|
}
|
|
else if( iY + 1 < psTransform->nGeoLocYSize &&
|
|
(!psTransform->bHasNoData ||
|
|
padfGLX[nXSize] != psTransform->dfNoDataX) )
|
|
{
|
|
padfX[i] = padfGLX[0]
|
|
+ (dfGeoLocLine -iY) * (padfGLX[nXSize] - padfGLX[0]);
|
|
padfY[i] = padfGLY[0]
|
|
+ (dfGeoLocLine -iY) * (padfGLY[nXSize] - padfGLY[0]);
|
|
}
|
|
else
|
|
{
|
|
padfX[i] = padfGLX[0];
|
|
padfY[i] = padfGLY[0];
|
|
}
|
|
|
|
panSuccess[i] = TRUE;
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* geox/geoy to pixel/line using backmap. */
|
|
/* -------------------------------------------------------------------- */
|
|
else
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < nPointCount; i++ )
|
|
{
|
|
if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
|
|
{
|
|
panSuccess[i] = FALSE;
|
|
continue;
|
|
}
|
|
|
|
double dfBMX, dfBMY;
|
|
int iBMX, iBMY;
|
|
|
|
dfBMX = ((padfX[i] - psTransform->adfBackMapGeoTransform[0])
|
|
/ psTransform->adfBackMapGeoTransform[1]);
|
|
dfBMY = ((padfY[i] - psTransform->adfBackMapGeoTransform[3])
|
|
/ psTransform->adfBackMapGeoTransform[5]);
|
|
|
|
iBMX = (int) dfBMX;
|
|
iBMY = (int) dfBMY;
|
|
|
|
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;
|
|
}
|
|
|
|
float* pafBMX = psTransform->pafBackMapX + iBM;
|
|
float* pafBMY = psTransform->pafBackMapY + iBM;
|
|
|
|
if( iBMX + 1 < psTransform->nBackMapWidth &&
|
|
iBMY + 1 < psTransform->nBackMapHeight &&
|
|
pafBMX[1] >=0 && pafBMX[psTransform->nBackMapWidth] >= 0 &&
|
|
pafBMX[psTransform->nBackMapWidth+1] >= 0)
|
|
{
|
|
padfX[i] = (1-(dfBMY - iBMY)) * (pafBMX[0] + (dfBMX - iBMX) * (pafBMX[1] - pafBMX[0])) +
|
|
(dfBMY - iBMY) * (pafBMX[psTransform->nBackMapWidth] +
|
|
(dfBMX - iBMX) * (pafBMX[psTransform->nBackMapWidth+1] - pafBMX[psTransform->nBackMapWidth]));
|
|
padfY[i] = (1-(dfBMY - iBMY)) * (pafBMY[0] + (dfBMX - iBMX) * (pafBMY[1] - pafBMY[0])) +
|
|
(dfBMY - iBMY) * (pafBMY[psTransform->nBackMapWidth] +
|
|
(dfBMX - iBMX) * (pafBMY[psTransform->nBackMapWidth+1] - pafBMY[psTransform->nBackMapWidth]));
|
|
}
|
|
else if( iBMX + 1 < psTransform->nBackMapWidth &&
|
|
pafBMX[1] >=0)
|
|
{
|
|
padfX[i] = pafBMX[0] +
|
|
(dfBMX - iBMX) * (pafBMX[1] - pafBMX[0]);
|
|
padfY[i] = pafBMY[0] +
|
|
(dfBMX - iBMX) * (pafBMY[1] - pafBMY[0]);
|
|
}
|
|
else if( iBMY + 1 < psTransform->nBackMapHeight &&
|
|
pafBMX[psTransform->nBackMapWidth] >= 0 )
|
|
{
|
|
padfX[i] = pafBMX[0] +
|
|
(dfBMY - iBMY) * (pafBMX[psTransform->nBackMapWidth] - pafBMX[0]);
|
|
padfY[i] = pafBMY[0] +
|
|
(dfBMY - iBMY) * (pafBMY[psTransform->nBackMapWidth] - pafBMY[0]);
|
|
}
|
|
else
|
|
{
|
|
padfX[i] = pafBMX[0];
|
|
padfY[i] = pafBMY[0];
|
|
}
|
|
panSuccess[i] = TRUE;
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* geox/geoy to pixel/line using search algorithm. */
|
|
/* -------------------------------------------------------------------- */
|
|
#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( 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;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALSerializeGeoLocTransformer() */
|
|
/************************************************************************/
|
|
|
|
CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg )
|
|
|
|
{
|
|
VALIDATE_POINTER1( pTransformArg, "GDALSerializeGeoLocTransformer", NULL );
|
|
|
|
CPLXMLNode *psTree;
|
|
GDALGeoLocTransformInfo *psInfo =
|
|
(GDALGeoLocTransformInfo *)(pTransformArg);
|
|
|
|
psTree = CPLCreateXMLNode( NULL, CXT_Element, "GeoLocTransformer" );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Serialize bReversed. */
|
|
/* -------------------------------------------------------------------- */
|
|
CPLCreateXMLElementAndValue(
|
|
psTree, "Reversed",
|
|
CPLString().Printf( "%d", psInfo->bReversed ) );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* geoloc metadata. */
|
|
/* -------------------------------------------------------------------- */
|
|
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;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALDeserializeGeoLocTransformer() */
|
|
/************************************************************************/
|
|
|
|
void *GDALDeserializeGeoLocTransformer( CPLXMLNode *psTree )
|
|
|
|
{
|
|
void *pResult;
|
|
int bReversed;
|
|
char **papszMD = NULL;
|
|
CPLXMLNode *psMDI, *psMetadata;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Collect metadata. */
|
|
/* -------------------------------------------------------------------- */
|
|
psMetadata = CPLGetXMLNode( psTree, "Metadata" );
|
|
|
|
if( psMetadata == NULL ||
|
|
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 );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Get other flags. */
|
|
/* -------------------------------------------------------------------- */
|
|
bReversed = atoi(CPLGetXMLValue(psTree,"Reversed","0"));
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Generate transformation. */
|
|
/* -------------------------------------------------------------------- */
|
|
pResult = GDALCreateGeoLocTransformer( NULL, papszMD, bReversed );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Cleanup GCP copy. */
|
|
/* -------------------------------------------------------------------- */
|
|
CSLDestroy( papszMD );
|
|
|
|
return pResult;
|
|
}
|