Skip to content

Commit a599c26

Browse files
authored
[cli][contour] Fix CLI issues OSGeo#11957 (OSGeo#11970)
Fixes OSGeo#11957 1. "gdal raster contour autotest/gcore/data/byte.tif out.gpkg", which lacks one of the required argument, shows the help message of the old gdal_contour utility. It should only indicate the name of one of the missing required arguments 2. "gdal raster contour --interval 1 autotest/gcore/data/byte.tif out.gpkg" repeated twice overwrites the output file. It should require a --overwrite flag to be specified to do that
1 parent 626a368 commit a599c26

File tree

6 files changed

+95
-8
lines changed

6 files changed

+95
-8
lines changed

apps/gdal_contour_lib.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ GDALContourAppOptionsGetParser(GDALContourOptions *psOptions,
441441
{
442442

443443
auto argParser = std::make_unique<GDALArgumentParser>(
444-
"gdal_contour", /* bForBinary */ true);
444+
"gdal_contour", /* bForBinary=*/psOptionsForBinary != nullptr);
445445

446446
argParser->add_description(_("Creates contour lines from a raster file."));
447447
argParser->add_epilog(_(

apps/gdal_translate_lib.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -3197,9 +3197,7 @@ std::string GDALTranslateGetParserUsage()
31973197
try
31983198
{
31993199
GDALTranslateOptions sOptions;
3200-
GDALTranslateOptionsForBinary sOptionsForBinary;
3201-
auto argParser =
3202-
GDALTranslateOptionsGetParser(&sOptions, &sOptionsForBinary);
3200+
auto argParser = GDALTranslateOptionsGetParser(&sOptions, nullptr);
32033201
return argParser->usage();
32043202
}
32053203
catch (const std::exception &err)

apps/gdalalg_raster_contour.cpp

+33-4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ GDALRasterContourAlgorithm::GDALRasterContourAlgorithm()
7171
AddArg("group-transactions", 0,
7272
_("Group n features per transaction (default 100 000)"),
7373
&m_groupTransactions);
74+
AddOverwriteArg(&m_overwrite);
7475
}
7576

7677
/************************************************************************/
@@ -166,18 +167,46 @@ bool GDALRasterContourAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
166167
aosOptions.AddString(m_outputLayerName);
167168
}
168169

170+
VSIStatBufL sStat;
171+
if (!m_overwrite && !m_outputDataset.GetName().empty() &&
172+
(VSIStatL(m_outputDataset.GetName().c_str(), &sStat) == 0 ||
173+
std::unique_ptr<GDALDataset>(
174+
GDALDataset::Open(m_outputDataset.GetName().c_str()))))
175+
{
176+
ReportError(CE_Failure, CPLE_AppDefined,
177+
"File '%s' already exists. Specify the --overwrite "
178+
"option to overwrite it.",
179+
m_outputDataset.GetName().c_str());
180+
return false;
181+
}
182+
183+
// Check that one of --interval, --levels, --exp-base is specified
184+
if (m_levels.size() == 0 && std::isnan(m_interval) && m_expBase == 0)
185+
{
186+
ReportError(
187+
CE_Failure, CPLE_AppDefined,
188+
"One of 'interval', 'levels', 'exp-base' must be specified.");
189+
return false;
190+
}
191+
192+
// Check that interval is not negative
193+
if (!std::isnan(m_interval) && m_interval < 0)
194+
{
195+
ReportError(CE_Failure, CPLE_AppDefined,
196+
"Interval must be a positive number.");
197+
return false;
198+
}
199+
169200
aosOptions.AddString(m_inputDataset.GetName());
170201
aosOptions.AddString(m_outputDataset.GetName());
171202

172-
GDALContourOptionsForBinary sOptionsForBinary;
203+
GDALContourOptionsForBinary optionsForBinary;
173204
std::unique_ptr<GDALContourOptions, decltype(&GDALContourOptionsFree)>
174-
psOptions{GDALContourOptionsNew(aosOptions.List(), &sOptionsForBinary),
205+
psOptions{GDALContourOptionsNew(aosOptions.List(), &optionsForBinary),
175206
GDALContourOptionsFree};
176207

177208
if (!psOptions)
178209
{
179-
CPLError(CE_Failure, CPLE_AppDefined,
180-
"Failed to create contour options: %s", CPLGetLastErrorMsg());
181210
return false;
182211
}
183212

apps/gdalalg_raster_contour.h

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class GDALRasterContourAlgorithm final : public GDALAlgorithm
8080
int m_expBase = 0; // -e <base>
8181
bool m_polygonize = false; // -p
8282
int m_groupTransactions = 0; // gt <n>
83+
bool m_overwrite = false; // -overwrite
8384
};
8485

8586
//! @endcond

autotest/utilities/test_gdalalg_raster_contour.py

+50
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ def get_contour_alg():
106106
True,
107107
"contour: Argument 'levels' is mutually exclusive with 'interval'.",
108108
),
109+
(
110+
[],
111+
True,
112+
"contour: One of 'interval', 'levels', 'exp-base' must be specified.",
113+
),
114+
(
115+
["--interval", "-10"],
116+
True,
117+
"contour: Interval must be a positive number.",
118+
),
109119
],
110120
)
111121
def test_gdalalg_raster_contour(tmp_vsimem, options, polygonize, expected_elev_values):
@@ -152,3 +162,43 @@ def test_gdalalg_raster_contour(tmp_vsimem, options, polygonize, expected_elev_v
152162
assert geom.GetGeometryType() == ogr.wkbLineString
153163
assert feat.GetField("ELEV") == expected_elev_values[i]
154164
lyr = None
165+
166+
167+
@pytest.mark.require_driver("AAIGRID")
168+
def test_gdalalg_raster_contour_overwrite(tmp_vsimem):
169+
170+
tmp_out_filename = str(tmp_vsimem / "out.shp")
171+
tmp_filename = str(tmp_vsimem / "tmp.asc")
172+
dem = """ncols 2
173+
nrows 2
174+
xllcorner 0
175+
yllcorner 0
176+
cellsize 1
177+
4 15
178+
25 36"""
179+
180+
gdal.FileFromMemBuffer(tmp_filename, dem.encode("ascii"))
181+
182+
pipeline = get_contour_alg()
183+
alg_options = [
184+
tmp_filename,
185+
tmp_out_filename,
186+
"--interval",
187+
"10",
188+
"--min-name",
189+
"ELEV_MIN",
190+
"--max-name",
191+
"ELEV_MAX",
192+
]
193+
194+
assert pipeline.ParseRunAndFinalize(alg_options)
195+
196+
# Run it again without --overwrite
197+
pipeline = get_contour_alg()
198+
with pytest.raises(RuntimeError, match="already exists"):
199+
pipeline.ParseRunAndFinalize(alg_options)
200+
201+
# Run it again with --overwrite
202+
pipeline = get_contour_alg()
203+
alg_options.append("--overwrite")
204+
assert pipeline.ParseRunAndFinalize(alg_options)

doc/source/programs/gdal_raster_contour.rst

+9
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Synopsis
5252
--off, --offset <OFFSET> Offset to apply to contour levels
5353
-p, --polygonize Create polygons instead of lines
5454
--group-transactions <GROUP-TRANSACTIONS> Group n features per transaction (default 100 000)
55+
--overwrite Whether overwriting existing output is allowed
5556
5657
Advanced Options:
5758
--oo, --open-option <KEY=VALUE> Open options [may be repeated]
@@ -67,6 +68,13 @@ The following options are available:
6768
Standard options
6869
++++++++++++++++
6970

71+
72+
.. include:: gdal_options/of_vector.rst
73+
74+
.. include:: gdal_options/co.rst
75+
76+
.. include:: gdal_options/overwrite.rst
77+
7078
.. option:: -b, --band <BAND>
7179

7280
Picks a particular band to get the DEM from. Defaults to band 1.
@@ -129,6 +137,7 @@ Advanced options
129137
.. include:: gdal_options/if.rst
130138

131139

140+
132141
Examples
133142
--------
134143

0 commit comments

Comments
 (0)