Skip to content

Commit

Permalink
Merge pull request OSGeo#2769 from rouault/fix_vrt_rounding
Browse files Browse the repository at this point in the history
Fix & improves issues related to VRT and SrcRect/DstRect
  • Loading branch information
rouault authored Jul 16, 2020
2 parents 0585986 + a560bf7 commit b99148c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 7 deletions.
11 changes: 11 additions & 0 deletions autotest/utilities/test_gdalbuildvrt_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,14 @@ def test_gdalbuildvrt_lib_ovr():
ds = None
gdal.GetDriverByName('VRT').Delete(tmpfilename)



def test_gdalbuildvrt_lib_te_partial_overlap():

ds = gdal.BuildVRT('', '../gcore/data/byte.tif', outputBounds=[440600, 3750060, 441860, 3751260], xRes=30, yRes=60)
assert ds is not None

assert ds.GetRasterBand(1).Checksum() == 8454
xml = ds.GetMetadata('xml:VRT')[0]
assert '<SrcRect xOff="0" yOff="1" xSize="19" ySize="19" />' in xml
assert '<DstRect xOff="4" yOff="0" xSize="38" ySize="19" />' in xml
33 changes: 27 additions & 6 deletions gdal/apps/gdalbuildvrt_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ static int ArgIsNumeric( const char *pszArg )
static int GetSrcDstWin(DatasetProperty* psDP,
double we_res, double ns_res,
double minX, double minY, double maxX, double maxY,
int nTargetXSize, int nTargetYSize,
double* pdfSrcXOff, double* pdfSrcYOff, double* pdfSrcXSize, double* pdfSrcYSize,
double* pdfDstXOff, double* pdfDstYOff, double* pdfDstXSize, double* pdfDstYSize)
{
Expand All @@ -140,8 +141,6 @@ static int GetSrcDstWin(DatasetProperty* psDP,
if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] < minY )
return FALSE;

*pdfSrcXSize = psDP->nRasterXSize;
*pdfSrcYSize = psDP->nRasterYSize;
if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X] < minX )
{
*pdfSrcXOff = (minX - psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X]) /
Expand All @@ -166,10 +165,30 @@ static int GetSrcDstWin(DatasetProperty* psDP,
*pdfDstYOff =
((maxY - psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]) / -ns_res);
}
*pdfDstXSize = (psDP->nRasterXSize *
psDP->adfGeoTransform[GEOTRSFRM_WE_RES] / we_res);
*pdfDstYSize = (psDP->nRasterYSize *
psDP->adfGeoTransform[GEOTRSFRM_NS_RES] / ns_res);

*pdfSrcXSize = psDP->nRasterXSize;
*pdfSrcYSize = psDP->nRasterYSize;
if( *pdfSrcXOff > 0 )
*pdfSrcXSize -= *pdfSrcXOff;
if( *pdfSrcYOff > 0 )
*pdfSrcYSize -= *pdfSrcYOff;

const double dfSrcToDstXSize = psDP->adfGeoTransform[GEOTRSFRM_WE_RES] / we_res;
*pdfDstXSize = *pdfSrcXSize * dfSrcToDstXSize;
const double dfSrcToDstYSize = psDP->adfGeoTransform[GEOTRSFRM_NS_RES] / ns_res;
*pdfDstYSize = *pdfSrcYSize * dfSrcToDstYSize;

if( *pdfDstXOff + *pdfDstXSize > nTargetXSize )
{
*pdfDstXSize = nTargetXSize - *pdfDstXOff;
*pdfSrcXSize = *pdfDstXSize / dfSrcToDstXSize;
}

if( *pdfDstYOff + *pdfDstYSize > nTargetYSize )
{
*pdfDstYSize = nTargetYSize - *pdfDstYOff;
*pdfSrcYSize = *pdfDstYSize / dfSrcToDstYSize;
}

return TRUE;
}
Expand Down Expand Up @@ -932,6 +951,7 @@ void VRTBuilder::CreateVRTSeparate(VRTDatasetH hVRTDS)
{
if ( ! GetSrcDstWin(psDatasetProperties,
we_res, ns_res, minX, minY, maxX, maxY,
nRasterXSize, nRasterYSize,
&dfSrcXOff, &dfSrcYOff, &dfSrcXSize, &dfSrcYSize,
&dfDstXOff, &dfDstYOff, &dfDstXSize, &dfDstYSize) )
continue;
Expand Down Expand Up @@ -1062,6 +1082,7 @@ void VRTBuilder::CreateVRTNonSeparate(VRTDatasetH hVRTDS)
double dfDstYSize;
if ( ! GetSrcDstWin(psDatasetProperties,
we_res, ns_res, minX, minY, maxX, maxY,
nRasterXSize, nRasterYSize,
&dfSrcXOff, &dfSrcYOff, &dfSrcXSize, &dfSrcYSize,
&dfDstXOff, &dfDstYOff, &dfDstXSize, &dfDstYSize) )
continue;
Expand Down
2 changes: 1 addition & 1 deletion gdal/frmts/vrt/vrtsources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ void VRTSimpleSource::SetSrcMaskBand( GDALRasterBand *poNewSrcBand )
static double RoundIfCloseToInt(double dfValue)
{
double dfClosestInt = floor(dfValue + 0.5);
return (fabs( dfValue - dfClosestInt ) < 1e-5) ? dfClosestInt : dfValue;
return (fabs( dfValue - dfClosestInt ) < 1e-3) ? dfClosestInt : dfValue;
}

/************************************************************************/
Expand Down

0 comments on commit b99148c

Please sign in to comment.