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