diff --git a/apps/gdalalg_raster_mosaic.cpp b/apps/gdalalg_raster_mosaic.cpp index 8c8eae01f187..bc4daf11b9bc 100644 --- a/apps/gdalalg_raster_mosaic.cpp +++ b/apps/gdalalg_raster_mosaic.cpp @@ -46,15 +46,18 @@ GDALRasterMosaicAlgorithm::GDALRasterMosaicAlgorithm() AddArg("band", 'b', _("Specify input band(s) number."), &m_bands); AddOverwriteArg(&m_overwrite); { - auto &arg = AddArg("resolution", 0, - _("Target resolution (in destination CRS units)"), - &m_resolution) - .SetMetaVar(",|average|highest|lowest"); + auto &arg = + AddArg("resolution", 0, + _("Target resolution (in destination CRS units)"), + &m_resolution) + .SetDefault("same") + .SetMetaVar(",|same|average|highest|lowest"); arg.AddValidationAction( [this, &arg]() { const std::string val = arg.Get(); - if (val != "average" && val != "highest" && val != "lowest") + if (val != "average" && val != "highest" && val != "lowest" && + val != "same") { const auto aosTokens = CPLStringList(CSLTokenizeString2(val.c_str(), ",", 0)); @@ -66,8 +69,8 @@ GDALRasterMosaicAlgorithm::GDALRasterMosaicAlgorithm() { ReportError(CE_Failure, CPLE_AppDefined, "resolution: two comma separated positive " - "values should be provided, or 'average', " - "'highest' or 'lowest'"); + "values should be provided, or 'same', " + "'average', 'highest' or 'lowest'"); return false; } } @@ -190,22 +193,20 @@ bool GDALRasterMosaicAlgorithm::RunImpl(GDALProgressFunc pfnProgress, aosOptions.push_back("-program_name"); aosOptions.push_back("gdal raster mosaic"); - if (!m_resolution.empty()) + const auto aosTokens = + CPLStringList(CSLTokenizeString2(m_resolution.c_str(), ",", 0)); + if (aosTokens.size() == 2) { - const auto aosTokens = - CPLStringList(CSLTokenizeString2(m_resolution.c_str(), ",", 0)); - if (aosTokens.size() == 2) - { - aosOptions.push_back("-tr"); - aosOptions.push_back(aosTokens[0]); - aosOptions.push_back(aosTokens[1]); - } - else - { - aosOptions.push_back("-resolution"); - aosOptions.push_back(m_resolution); - } + aosOptions.push_back("-tr"); + aosOptions.push_back(aosTokens[0]); + aosOptions.push_back(aosTokens[1]); + } + else + { + aosOptions.push_back("-resolution"); + aosOptions.push_back(m_resolution); } + if (!m_bbox.empty()) { aosOptions.push_back("-te"); diff --git a/apps/gdalalg_raster_stack.cpp b/apps/gdalalg_raster_stack.cpp index 41292a2b6775..0a56cc7d4bbd 100644 --- a/apps/gdalalg_raster_stack.cpp +++ b/apps/gdalalg_raster_stack.cpp @@ -46,15 +46,18 @@ GDALRasterStackAlgorithm::GDALRasterStackAlgorithm() AddArg("band", 'b', _("Specify input band(s) number."), &m_bands); AddOverwriteArg(&m_overwrite); { - auto &arg = AddArg("resolution", 0, - _("Target resolution (in destination CRS units)"), - &m_resolution) - .SetMetaVar(",|average|highest|lowest"); + auto &arg = + AddArg("resolution", 0, + _("Target resolution (in destination CRS units)"), + &m_resolution) + .SetDefault("same") + .SetMetaVar(",|same|average|highest|lowest"); arg.AddValidationAction( [this, &arg]() { const std::string val = arg.Get(); - if (val != "average" && val != "highest" && val != "lowest") + if (val != "average" && val != "highest" && val != "lowest" && + val != "same") { const auto aosTokens = CPLStringList(CSLTokenizeString2(val.c_str(), ",", 0)); @@ -66,8 +69,8 @@ GDALRasterStackAlgorithm::GDALRasterStackAlgorithm() { ReportError(CE_Failure, CPLE_AppDefined, "resolution: two comma separated positive " - "values should be provided, or 'average', " - "'highest' or 'lowest'"); + "values should be provided, or 'same', " + "'average', 'highest' or 'lowest'"); return false; } } @@ -188,22 +191,20 @@ bool GDALRasterStackAlgorithm::RunImpl(GDALProgressFunc pfnProgress, aosOptions.push_back("-separate"); - if (!m_resolution.empty()) + const auto aosTokens = + CPLStringList(CSLTokenizeString2(m_resolution.c_str(), ",", 0)); + if (aosTokens.size() == 2) { - const auto aosTokens = - CPLStringList(CSLTokenizeString2(m_resolution.c_str(), ",", 0)); - if (aosTokens.size() == 2) - { - aosOptions.push_back("-tr"); - aosOptions.push_back(aosTokens[0]); - aosOptions.push_back(aosTokens[1]); - } - else - { - aosOptions.push_back("-resolution"); - aosOptions.push_back(m_resolution); - } + aosOptions.push_back("-tr"); + aosOptions.push_back(aosTokens[0]); + aosOptions.push_back(aosTokens[1]); + } + else + { + aosOptions.push_back("-resolution"); + aosOptions.push_back(m_resolution); } + if (!m_bbox.empty()) { aosOptions.push_back("-te"); diff --git a/autotest/utilities/test_gdalalg_raster_mosaic.py b/autotest/utilities/test_gdalalg_raster_mosaic.py index 95b36eca9c90..414d871a9f07 100755 --- a/autotest/utilities/test_gdalalg_raster_mosaic.py +++ b/autotest/utilities/test_gdalalg_raster_mosaic.py @@ -115,6 +115,7 @@ def test_gdalalg_raster_mosaic_resolution_average(): alg = get_mosaic_alg() alg.GetArg("input").Set([src1_ds, src2_ds]) + alg.GetArg("resolution").Set("average") alg.GetArg("output").Set("") assert alg.Run() ds = alg.GetArg("output").Get().GetDataset() @@ -196,24 +197,41 @@ def test_gdalalg_raster_mosaic_target_aligned_pixels(): assert ds.GetGeoTransform() == pytest.approx((1.8, 0.3, 0.0, 49.2, 0.0, -0.6)) +def test_gdalalg_raster_mosaic_resolution_same_default(): + + src1_ds = gdal.GetDriverByName("MEM").Create("", 1, 1) + src1_ds.SetGeoTransform([2, 1, 0, 49, 0, -1]) + src2_ds = gdal.GetDriverByName("MEM").Create("", 2, 2) + src2_ds.SetGeoTransform([3, 0.5, 0, 49, 0, -0.5]) + + alg = get_mosaic_alg() + alg.GetArg("input").Set([src1_ds, src2_ds]) + alg.GetArg("output").Set("") + with pytest.raises( + Exception, + match="whereas previous sources have resolution", + ): + assert alg.Run() + + def test_gdalalg_raster_mosaic_resolution_invalid(): alg = get_mosaic_alg() with pytest.raises( Exception, - match="resolution: two comma separated positive values should be provided, or 'average', 'highest' or 'lowest'", + match="resolution: two comma separated positive values should be provided, or 'same', 'average', 'highest' or 'lowest'", ): alg.GetArg("resolution").Set("invalid") with pytest.raises( Exception, - match="resolution: two comma separated positive values should be provided, or 'average', 'highest' or 'lowest'", + match="resolution: two comma separated positive values should be provided, or 'same', 'average', 'highest' or 'lowest'", ): alg.GetArg("resolution").Set("0.5") with pytest.raises( Exception, - match="resolution: two comma separated positive values should be provided, or 'average', 'highest' or 'lowest'", + match="resolution: two comma separated positive values should be provided, or 'same', 'average', 'highest' or 'lowest'", ): alg.GetArg("resolution").Set("-0.5,-0.5") diff --git a/doc/source/programs/gdal_raster_mosaic.rst b/doc/source/programs/gdal_raster_mosaic.rst index 4cb66f440c20..abdf14d848a2 100644 --- a/doc/source/programs/gdal_raster_mosaic.rst +++ b/doc/source/programs/gdal_raster_mosaic.rst @@ -22,30 +22,29 @@ Synopsis Build a mosaic, either virtual (VRT) or materialized Positional arguments: - -i, --input Input raster datasets (or specify a @ to point to a file containing filenames) [1.. values] - -o, --output Output raster dataset (created by algorithm) [required] + -i, --input Input raster datasets (or specify a @ to point to a file containing filenames) [1.. values] + -o, --output Output raster dataset (created by algorithm) [required] Common Options: - -h, --help Display help message and exit - --version Display GDAL version and exit - --json-usage Display usage as JSON document and exit - --drivers Display driver list as JSON document and exit - --config = Configuration option [may be repeated] - --progress Display progress bar + -h, --help Display help message and exit + --version Display GDAL version and exit + --json-usage Display usage as JSON document and exit + --drivers Display driver list as JSON document and exit + --config = Configuration option [may be repeated] + --progress Display progress bar Options: - -f, --of, --format, --output-format Output format - --co, --creation-option = Creation option [may be repeated] - -b, --band Specify input band(s) number. [may be repeated] - --overwrite Whether overwriting existing output is allowed - --resolution ,|average|highest|lowest> Target resolution (in destination CRS units) - --bbox Target bounding box as xmin,ymin,xmax,ymax (in destination CRS units) - --target-aligned-pixels Round target extent to target resolution - --srcnodata Set nodata values for input bands. [1.. values] - --dstnodata Set nodata values at the destination band level. [1.. values] - --hidenodata Makes the destination band not report the NoData. - --addalpha Adds an alpha mask band to the destination when the source raster have none. - + -f, --of, --format, --output-format Output format + --co, --creation-option = Creation option [may be repeated] + -b, --band Specify input band(s) number. [may be repeated] + --overwrite Whether overwriting existing output is allowed + --resolution ,|same|average|highest|lowest> Target resolution (in destination CRS units) (default: same) + --bbox Target bounding box as xmin,ymin,xmax,ymax (in destination CRS units) + --target-aligned-pixels Round target extent to target resolution + --srcnodata Set nodata values for input bands. [1.. values] + --dstnodata Set nodata values at the destination band level. [1.. values] + --hidenodata Makes the destination band not report the NoData. + --addalpha Adds an alpha mask band to the destination when the source raster have none. Description @@ -86,16 +85,18 @@ The following options are available: If input bands not set all bands will be added to the output. Multiple :option:`-b` switches may be used to select a set of input bands. -.. option:: --resolution {|highest|lowest|average} +.. option:: --resolution {|same|highest|lowest|average} 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. + `same`, the default, checks that all source rasters have the same resolution and errors out when this is not the case. + `highest` will pick the smallest values of pixel dimensions within the set of source rasters. `lowest` will pick the largest values of pixel dimensions within the set of source rasters. - `average` is the default and will compute an average of pixel dimensions within the set of source rasters. + `average` will compute an average of pixel dimensions within the set of source rasters. ,. The values must be expressed in georeferenced units. Both must be positive values. diff --git a/doc/source/programs/gdal_raster_stack.rst b/doc/source/programs/gdal_raster_stack.rst index a43a702ed6a7..835a9945203c 100644 --- a/doc/source/programs/gdal_raster_stack.rst +++ b/doc/source/programs/gdal_raster_stack.rst @@ -23,29 +23,28 @@ Synopsis Combine together input bands into a multi-band output, either virtual (VRT) or materialized. Positional arguments: - -i, --input Input raster datasets (or specify a @ to point to a file containing filenames) [1.. values] - -o, --output Output raster dataset (created by algorithm) [required] + -i, --input Input raster datasets (or specify a @ to point to a file containing filenames) [1.. values] + -o, --output Output raster dataset (created by algorithm) [required] Common Options: - -h, --help Display help message and exit - --version Display GDAL version and exit - --json-usage Display usage as JSON document and exit - --drivers Display driver list as JSON document and exit - --config = Configuration option [may be repeated] - --progress Display progress bar + -h, --help Display help message and exit + --version Display GDAL version and exit + --json-usage Display usage as JSON document and exit + --drivers Display driver list as JSON document and exit + --config = Configuration option [may be repeated] + --progress Display progress bar Options: - -f, --of, --format, --output-format Output format - --co, --creation-option = Creation option [may be repeated] - -b, --band Specify input band(s) number. [may be repeated] - --overwrite Whether overwriting existing output is allowed - --resolution ,|average|highest|lowest> Target resolution (in destination CRS units) - --bbox Target bounding box as xmin,ymin,xmax,ymax (in destination CRS units) - --target-aligned-pixels Round target extent to target resolution - --srcnodata Set nodata values for input bands. [1.. values] - --dstnodata Set nodata values at the destination band level. [1.. values] - --hidenodata Makes the destination band not report the NoData. - + -f, --of, --format, --output-format Output format + --co, --creation-option = Creation option [may be repeated] + -b, --band Specify input band(s) number. [may be repeated] + --overwrite Whether overwriting existing output is allowed + --resolution ,|same|average|highest|lowest> Target resolution (in destination CRS units) (default: same) + --bbox Target bounding box as xmin,ymin,xmax,ymax (in destination CRS units) + --target-aligned-pixels Round target extent to target resolution + --srcnodata Set nodata values for input bands. [1.. values] + --dstnodata Set nodata values at the destination band level. [1.. values] + --hidenodata Makes the destination band not report the NoData. Description @@ -77,16 +76,18 @@ The following options are available: If input bands not set all bands will be added to the output. Multiple :option:`-b` switches may be used to select a set of input bands. -.. option:: --resolution {|highest|lowest|average} +.. option:: --resolution {|same|highest|lowest|average} 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. + `same`, the default, checks that all source rasters have the same resolution and errors out when this is not the case. + `highest` will pick the smallest values of pixel dimensions within the set of source rasters. `lowest` will pick the largest values of pixel dimensions within the set of source rasters. - `average` is the default and will compute an average of pixel dimensions within the set of source rasters. + `average` will compute an average of pixel dimensions within the set of source rasters. ,. The values must be expressed in georeferenced units. Both must be positive values. diff --git a/ogr/gml2ogrgeometry.cpp b/ogr/gml2ogrgeometry.cpp index 5f79556f82c0..6ce1d011d5f9 100644 --- a/ogr/gml2ogrgeometry.cpp +++ b/ogr/gml2ogrgeometry.cpp @@ -2043,9 +2043,15 @@ GML2OGRGeometry_XMLNode_Internal(const CPLXMLNode *psNode, const char *pszId, p.setX(dfCenterX - dfRadius); p.setY(dfCenterY); poCC->addPoint(&p); + p.setX(dfCenterX); + p.setY(dfCenterY + dfRadius); + poCC->addPoint(&p); p.setX(dfCenterX + dfRadius); p.setY(dfCenterY); poCC->addPoint(&p); + p.setX(dfCenterX); + p.setY(dfCenterY - dfRadius); + poCC->addPoint(&p); p.setX(dfCenterX - dfRadius); p.setY(dfCenterY); poCC->addPoint(&p);