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