From cd728bdaead5954d51bde0bab849c8f10ab89d04 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 27 Jan 2025 16:28:48 +0100 Subject: [PATCH] gdalbuildvrt: add '-resolution same' mode to check all source rasters have the same resolution --- apps/gdalbuildvrt_lib.cpp | 25 +++++++++++++++++++++++-- doc/source/programs/gdalbuildvrt.rst | 8 +++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/apps/gdalbuildvrt_lib.cpp b/apps/gdalbuildvrt_lib.cpp index 43441e18c052..2491fcbab006 100644 --- a/apps/gdalbuildvrt_lib.cpp +++ b/apps/gdalbuildvrt_lib.cpp @@ -63,6 +63,7 @@ typedef enum LOWEST_RESOLUTION, HIGHEST_RESOLUTION, AVERAGE_RESOLUTION, + SAME_RESOLUTION, USER_RESOLUTION } ResolutionStrategy; @@ -985,6 +986,23 @@ std::string VRTBuilder::AnalyseRaster(GDALDatasetH hDS, ns_res += dfDelta / nCountValid; } } + else if (resolutionStrategy == SAME_RESOLUTION) + { + if (bFirst) + { + we_res = padfGeoTransform[GEOTRSFRM_WE_RES]; + ns_res = padfGeoTransform[GEOTRSFRM_NS_RES]; + } + else if (we_res != padfGeoTransform[GEOTRSFRM_WE_RES] || + ns_res != padfGeoTransform[GEOTRSFRM_NS_RES]) + { + return CPLSPrintf("Dataset %s has resolution %f x %f, whereas " + "previous sources have resolution %f x %f", + dsFileName, padfGeoTransform[GEOTRSFRM_WE_RES], + padfGeoTransform[GEOTRSFRM_NS_RES], we_res, + ns_res); + } + } else if (resolutionStrategy != USER_RESOLUTION) { if (bFirst) @@ -1922,6 +1940,8 @@ GDALDatasetH GDALBuildVRT(const char *pszDest, int nSrcCount, eStrategy = HIGHEST_RESOLUTION; else if (EQUAL(sOptions.osResolution.c_str(), "lowest")) eStrategy = LOWEST_RESOLUTION; + else if (EQUAL(sOptions.osResolution.c_str(), "same")) + eStrategy = SAME_RESOLUTION; /* If -srcnodata is specified, use it as the -vrtnodata if the latter is not */ @@ -2055,7 +2075,7 @@ GDALBuildVRTOptionsGetParser(GDALBuildVRTOptions *psOptions, "the default value which is 'location'.")); argParser->add_argument("-resolution") - .metavar("user|average|highest|lowest") + .metavar("user|average|highest|lowest|same") .action( [psOptions](const std::string &s) { @@ -2063,7 +2083,8 @@ GDALBuildVRTOptionsGetParser(GDALBuildVRTOptions *psOptions, if (!EQUAL(psOptions->osResolution.c_str(), "user") && !EQUAL(psOptions->osResolution.c_str(), "average") && !EQUAL(psOptions->osResolution.c_str(), "highest") && - !EQUAL(psOptions->osResolution.c_str(), "lowest")) + !EQUAL(psOptions->osResolution.c_str(), "lowest") && + !EQUAL(psOptions->osResolution.c_str(), "same")) { throw std::invalid_argument( CPLSPrintf("Illegal resolution value (%s).", diff --git a/doc/source/programs/gdalbuildvrt.rst b/doc/source/programs/gdalbuildvrt.rst index 26fcd5122e54..e8c66f6006f8 100644 --- a/doc/source/programs/gdalbuildvrt.rst +++ b/doc/source/programs/gdalbuildvrt.rst @@ -19,8 +19,8 @@ Synopsis [--quiet] [[-strict]|[-non_strict]] [-tile_index ] - [-resolution user|average|highest|lowest] [-tr ] - [-input_file_list ] [-separate] + [-resolution user|average|highest|lowest|same] + [-tr ] [-input_file_list ] [-separate] [-allow_projection_difference] [-sd ] [-tap] [-te ] [-addalpha] [-b ]... [-hidenodata] [-overwrite] @@ -79,7 +79,7 @@ changed in later versions. Use the specified value as the tile index field, instead of the default value which is 'location'. -.. option:: -resolution {highest|lowest|average|user} +.. option:: -resolution {highest|lowest|average|user|same} In case the resolution of all input files is not the same, the :option:`-resolution` flag enables the user to control the way the output resolution is computed. @@ -92,6 +92,8 @@ changed in later versions. `user` must be used in combination with the :option:`-tr` option to specify the target resolution. + `same` (added in GDAL 3.11) checks that all source rasters have the same resolution and errors out when this is not the case. + .. option:: -tr Set target resolution. The values must be expressed in georeferenced units.