Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: gdal "vector rasterize" subcommand
5 : * Author: Alessandro Pasotti <elpaso at itopen dot it>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2025, Alessandro Pasotti <elpaso at itopen dot it>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include <cmath>
14 :
15 : #include "gdalalg_vector_rasterize.h"
16 : #include "gdalalg_raster_write.h"
17 :
18 : #include "cpl_conv.h"
19 : #include "gdal_priv.h"
20 : #include "gdal_utils.h"
21 :
22 : //! @cond Doxygen_Suppress
23 :
24 : #ifndef _
25 : #define _(x) (x)
26 : #endif
27 :
28 : /************************************************************************/
29 : /* GDALVectorRasterizeAlgorithm::GDALVectorRasterizeAlgorithm() */
30 : /************************************************************************/
31 :
32 41 : GDALVectorRasterizeAlgorithm::GDALVectorRasterizeAlgorithm(bool bStandaloneStep)
33 : : GDALPipelineStepAlgorithm(
34 : NAME, DESCRIPTION, HELP_URL,
35 0 : ConstructorOptions()
36 41 : .SetStandaloneStep(bStandaloneStep)
37 82 : .SetOutputFormatCreateCapability(GDAL_DCAP_CREATE))
38 : {
39 41 : AddProgressArg();
40 41 : if (bStandaloneStep)
41 : {
42 34 : AddOutputFormatArg(&m_format)
43 : .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES,
44 136 : {GDAL_DCAP_RASTER, GDAL_DCAP_CREATE})
45 68 : .AddMetadataItem(GAAMDI_VRT_COMPATIBLE, {"false"});
46 34 : AddOpenOptionsArg(&m_openOptions);
47 34 : AddInputFormatsArg(&m_inputFormats)
48 68 : .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES, {GDAL_DCAP_VECTOR});
49 34 : AddInputDatasetArg(&m_inputDataset, GDAL_OF_VECTOR)
50 34 : .SetMinCount(1)
51 34 : .SetMaxCount(1);
52 34 : AddOutputDatasetArg(&m_outputDataset, GDAL_OF_RASTER)
53 34 : .SetDatasetInputFlags(GADV_NAME | GADV_OBJECT);
54 34 : AddCreationOptionsArg(&m_creationOptions);
55 34 : AddOverwriteArg(&m_overwrite);
56 : }
57 :
58 41 : AddBandArg(&m_bands, _("The band(s) to burn values into (1-based index)"));
59 82 : AddArg("invert", 0, _("Invert the rasterization"), &m_invert)
60 41 : .SetDefault(false);
61 : AddArg("all-touched", 0, _("Enables the ALL_TOUCHED rasterization option"),
62 41 : &m_allTouched);
63 41 : AddArg("burn", 0, _("Burn value"), &m_burnValues);
64 41 : AddArg("attribute-name", 'a', _("Attribute name"), &m_attributeName);
65 : AddArg("3d", 0,
66 : _("Indicates that a burn value should be extracted from the Z"
67 : " values of the feature"),
68 41 : &m_3d);
69 82 : AddArg("layer-name", 'l', _("Layer name"), &m_layerName)
70 82 : .AddAlias("layer")
71 41 : .SetMutualExclusionGroup("layer-name-or-sql");
72 41 : AddArg("where", 0, _("SQL where clause"), &m_where);
73 82 : AddArg("sql", 0, _("SQL select statement"), &m_sql)
74 41 : .SetMutualExclusionGroup("layer-name-or-sql");
75 41 : AddArg("dialect", 0, _("SQL dialect"), &m_dialect);
76 : AddArg("nodata", 0, _("Assign a specified nodata value to output bands"),
77 41 : &m_nodata);
78 : AddArg("init", 0, _("Pre-initialize output bands with specified value"),
79 41 : &m_initValues);
80 82 : AddArg("crs", 0, _("Override the projection for the output file"), &m_srs)
81 82 : .AddHiddenAlias("srs")
82 41 : .SetIsCRSArg(/*noneAllowed=*/false);
83 : AddArg("transformer-option", 0,
84 : _("Set a transformer option suitable to pass to "
85 : "GDALCreateGenImgProjTransformer2"),
86 82 : &m_transformerOption)
87 41 : .SetMetaVar("<NAME>=<VALUE>");
88 : AddArg("extent", 0, _("Set the target georeferenced extent"),
89 82 : &m_targetExtent)
90 41 : .SetMinCount(4)
91 41 : .SetMaxCount(4)
92 41 : .SetRepeatedArgAllowed(false)
93 41 : .SetMetaVar("<xmin>,<ymin>,<xmax>,<ymax>");
94 82 : AddArg("resolution", 0, _("Set the target resolution"), &m_targetResolution)
95 41 : .SetMinCount(2)
96 41 : .SetMaxCount(2)
97 41 : .SetRepeatedArgAllowed(false)
98 82 : .SetMetaVar("<xres>,<yres>")
99 41 : .SetMutualExclusionGroup("size-or-resolution");
100 : AddArg("target-aligned-pixels", 0,
101 : _("(target aligned pixels) Align the coordinates of the extent of "
102 : "the output file to the values of the resolution"),
103 82 : &m_tap)
104 41 : .AddAlias("tap");
105 : AddArg("size", 0, _("Set the target size in pixels and lines"),
106 82 : &m_targetSize)
107 41 : .SetMinCount(2)
108 41 : .SetMaxCount(2)
109 41 : .SetRepeatedArgAllowed(false)
110 82 : .SetMetaVar("<xsize>,<ysize>")
111 41 : .SetMutualExclusionGroup("size-or-resolution");
112 41 : AddOutputDataTypeArg(&m_outputType);
113 : AddArg("optimization", 0,
114 : _("Force the algorithm used (results are identical)"),
115 82 : &m_optimization)
116 41 : .SetChoices("AUTO", "RASTER", "VECTOR")
117 41 : .SetDefault("AUTO");
118 :
119 41 : if (bStandaloneStep)
120 : {
121 68 : auto &addArg = AddArg("add", 0, _("Add to existing raster"), &m_add)
122 34 : .SetDefault(false);
123 34 : auto &updateArg = AddUpdateArg(&m_update);
124 : addArg.AddValidationAction(
125 1 : [&updateArg]()
126 : {
127 1 : updateArg.Set(true);
128 1 : return true;
129 34 : });
130 : }
131 41 : }
132 :
133 : /************************************************************************/
134 : /* GDALVectorRasterizeAlgorithm::RunStep() */
135 : /************************************************************************/
136 :
137 28 : bool GDALVectorRasterizeAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt)
138 : {
139 28 : auto poSrcDS = m_inputDataset[0].GetDatasetRef();
140 28 : CPLAssert(poSrcDS);
141 :
142 56 : CPLStringList aosOptions;
143 :
144 28 : if (m_bands.size())
145 : {
146 72 : for (int band : m_bands)
147 : {
148 54 : aosOptions.AddString("-b");
149 54 : aosOptions.AddString(CPLSPrintf("%d", band));
150 : }
151 : }
152 :
153 28 : if (m_invert)
154 : {
155 1 : aosOptions.AddString("-i");
156 : }
157 :
158 28 : if (m_allTouched)
159 : {
160 25 : aosOptions.AddString("-at");
161 : }
162 :
163 28 : if (m_burnValues.size())
164 : {
165 92 : for (double burnValue : m_burnValues)
166 : {
167 69 : aosOptions.AddString("-burn");
168 69 : aosOptions.AddString(CPLSPrintf("%.17g", burnValue));
169 : }
170 : }
171 :
172 28 : if (!m_attributeName.empty())
173 : {
174 3 : aosOptions.AddString("-a");
175 3 : aosOptions.AddString(m_attributeName.c_str());
176 : }
177 :
178 28 : if (m_3d)
179 : {
180 2 : aosOptions.AddString("-3d");
181 : }
182 :
183 28 : if (m_add)
184 : {
185 1 : aosOptions.AddString("-add");
186 : // Implies update
187 1 : m_update = true;
188 : }
189 :
190 28 : if (!m_layerName.empty())
191 : {
192 19 : aosOptions.AddString("-l");
193 19 : aosOptions.AddString(m_layerName.c_str());
194 : }
195 :
196 28 : if (!m_where.empty())
197 : {
198 1 : aosOptions.AddString("-where");
199 1 : aosOptions.AddString(m_where.c_str());
200 : }
201 :
202 28 : if (!m_sql.empty())
203 : {
204 4 : aosOptions.AddString("-sql");
205 4 : aosOptions.AddString(m_sql.c_str());
206 : }
207 :
208 28 : if (!m_dialect.empty())
209 : {
210 3 : aosOptions.AddString("-dialect");
211 3 : aosOptions.AddString(m_dialect.c_str());
212 : }
213 :
214 56 : std::string outputFilename;
215 28 : if (m_standaloneStep)
216 : {
217 27 : outputFilename = m_outputDataset.GetName();
218 27 : if (!m_format.empty())
219 : {
220 1 : aosOptions.AddString("-of");
221 1 : aosOptions.AddString(m_format.c_str());
222 : }
223 :
224 28 : for (const std::string &co : m_creationOptions)
225 : {
226 1 : aosOptions.AddString("-co");
227 1 : aosOptions.AddString(co.c_str());
228 : }
229 : }
230 : else
231 : {
232 1 : outputFilename = CPLGenerateTempFilenameSafe("_rasterize.tif");
233 :
234 1 : aosOptions.AddString("-of");
235 1 : aosOptions.AddString("GTiff");
236 :
237 1 : aosOptions.AddString("-co");
238 1 : aosOptions.AddString("TILED=YES");
239 : }
240 :
241 28 : if (!std::isnan(m_nodata))
242 : {
243 1 : aosOptions.AddString("-a_nodata");
244 1 : aosOptions.AddString(CPLSPrintf("%.17g", m_nodata));
245 : }
246 :
247 28 : if (m_initValues.size())
248 : {
249 12 : for (double initValue : m_initValues)
250 : {
251 9 : aosOptions.AddString("-init");
252 9 : aosOptions.AddString(CPLSPrintf("%.17g", initValue));
253 : }
254 : }
255 :
256 28 : if (!m_srs.empty())
257 : {
258 1 : aosOptions.AddString("-a_srs");
259 1 : aosOptions.AddString(m_srs.c_str());
260 : }
261 :
262 28 : if (m_transformerOption.size())
263 : {
264 0 : for (const auto &to : m_transformerOption)
265 : {
266 0 : aosOptions.AddString("-to");
267 0 : aosOptions.AddString(to.c_str());
268 : }
269 : }
270 :
271 28 : if (m_targetExtent.size())
272 : {
273 1 : aosOptions.AddString("-te");
274 5 : for (double targetExtent : m_targetExtent)
275 : {
276 4 : aosOptions.AddString(CPLSPrintf("%.17g", targetExtent));
277 : }
278 : }
279 :
280 28 : if (m_targetResolution.size())
281 : {
282 6 : aosOptions.AddString("-tr");
283 18 : for (double targetResolution : m_targetResolution)
284 : {
285 12 : aosOptions.AddString(CPLSPrintf("%.17g", targetResolution));
286 : }
287 : }
288 :
289 28 : if (m_tap)
290 : {
291 1 : aosOptions.AddString("-tap");
292 : }
293 :
294 28 : if (m_targetSize.size())
295 : {
296 5 : aosOptions.AddString("-ts");
297 15 : for (int targetSize : m_targetSize)
298 : {
299 10 : aosOptions.AddString(CPLSPrintf("%d", targetSize));
300 : }
301 : }
302 :
303 28 : if (!m_outputType.empty())
304 : {
305 0 : aosOptions.AddString("-ot");
306 0 : aosOptions.AddString(m_outputType.c_str());
307 : }
308 :
309 28 : if (!m_optimization.empty())
310 : {
311 28 : aosOptions.AddString("-optim");
312 28 : aosOptions.AddString(m_optimization.c_str());
313 : }
314 :
315 28 : bool bOK = false;
316 : std::unique_ptr<GDALRasterizeOptions, decltype(&GDALRasterizeOptionsFree)>
317 : psOptions{GDALRasterizeOptionsNew(aosOptions.List(), nullptr),
318 28 : GDALRasterizeOptionsFree};
319 28 : if (psOptions)
320 : {
321 24 : GDALRasterizeOptionsSetProgress(psOptions.get(), ctxt.m_pfnProgress,
322 : ctxt.m_pProgressData);
323 :
324 : GDALDatasetH hDstDS =
325 24 : GDALDataset::ToHandle(m_outputDataset.GetDatasetRef());
326 :
327 24 : GDALDatasetH hSrcDS = GDALDataset::ToHandle(poSrcDS);
328 24 : auto poRetDS = GDALDataset::FromHandle(GDALRasterize(
329 24 : outputFilename.c_str(), hDstDS, hSrcDS, psOptions.get(), nullptr));
330 24 : bOK = poRetDS != nullptr;
331 :
332 24 : if (!hDstDS)
333 : {
334 11 : if (!m_standaloneStep && poRetDS)
335 : {
336 1 : VSIUnlink(outputFilename.c_str());
337 1 : poRetDS->MarkSuppressOnClose();
338 : }
339 :
340 11 : m_outputDataset.Set(std::unique_ptr<GDALDataset>(poRetDS));
341 : }
342 : }
343 :
344 56 : return bOK;
345 : }
346 :
347 : /************************************************************************/
348 : /* GDALVectorRasterizeAlgorithm::RunImpl() */
349 : /************************************************************************/
350 :
351 27 : bool GDALVectorRasterizeAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
352 : void *pProgressData)
353 : {
354 27 : GDALPipelineStepRunContext stepCtxt;
355 27 : stepCtxt.m_pfnProgress = pfnProgress;
356 27 : stepCtxt.m_pProgressData = pProgressData;
357 27 : return RunPreStepPipelineValidations() && RunStep(stepCtxt);
358 : }
359 :
360 : GDALVectorRasterizeAlgorithmStandalone::
361 : ~GDALVectorRasterizeAlgorithmStandalone() = default;
362 :
363 : //! @endcond
|