/src/gdal/apps/gdalalg_vector_pipeline.cpp
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: GDAL |
4 | | * Purpose: gdal "vector pipeline" subcommand |
5 | | * Author: Even Rouault <even dot rouault at spatialys.com> |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com> |
9 | | * |
10 | | * SPDX-License-Identifier: MIT |
11 | | ****************************************************************************/ |
12 | | |
13 | | #include "gdalalg_vector_pipeline.h" |
14 | | #include "gdalalg_external.h" |
15 | | #include "gdalalg_materialize.h" |
16 | | #include "gdalalg_vector_read.h" |
17 | | #include "gdalalg_vector_buffer.h" |
18 | | #include "gdalalg_vector_check_coverage.h" |
19 | | #include "gdalalg_vector_check_geometry.h" |
20 | | #include "gdalalg_vector_clean_coverage.h" |
21 | | #include "gdalalg_vector_clip.h" |
22 | | #include "gdalalg_vector_combine.h" |
23 | | #include "gdalalg_vector_compare.h" |
24 | | #include "gdalalg_vector_concat.h" |
25 | | #include "gdalalg_vector_concave_hull.h" |
26 | | #include "gdalalg_vector_convex_hull.h" |
27 | | #include "gdalalg_vector_create.h" |
28 | | #include "gdalalg_vector_dissolve.h" |
29 | | #include "gdalalg_vector_edit.h" |
30 | | #include "gdalalg_vector_explode.h" |
31 | | #include "gdalalg_vector_explode_collections.h" |
32 | | #include "gdalalg_vector_export_schema.h" |
33 | | #include "gdalalg_vector_filter.h" |
34 | | #include "gdalalg_vector_info.h" |
35 | | #include "gdalalg_vector_layer_algebra.h" |
36 | | #include "gdalalg_vector_limit.h" |
37 | | #include "gdalalg_vector_make_point.h" |
38 | | #include "gdalalg_vector_make_valid.h" |
39 | | #include "gdalalg_vector_partition.h" |
40 | | #include "gdalalg_vector_rename_layer.h" |
41 | | #include "gdalalg_vector_reproject.h" |
42 | | #include "gdalalg_vector_segmentize.h" |
43 | | #include "gdalalg_vector_select.h" |
44 | | #include "gdalalg_vector_set_field_type.h" |
45 | | #include "gdalalg_vector_set_geom_type.h" |
46 | | #include "gdalalg_vector_simplify.h" |
47 | | #include "gdalalg_vector_simplify_coverage.h" |
48 | | #include "gdalalg_vector_sort.h" |
49 | | #include "gdalalg_vector_sql.h" |
50 | | #include "gdalalg_vector_swap_xy.h" |
51 | | #include "gdalalg_vector_update.h" |
52 | | #include "gdalalg_vector_write.h" |
53 | | #include "gdalalg_tee.h" |
54 | | |
55 | | #include "../frmts/mem/memdataset.h" |
56 | | |
57 | | #include "cpl_conv.h" |
58 | | #include "cpl_string.h" |
59 | | |
60 | | #include <algorithm> |
61 | | #include <cassert> |
62 | | |
63 | | //! @cond Doxygen_Suppress |
64 | | |
65 | | #ifndef _ |
66 | | #define _(x) (x) |
67 | | #endif |
68 | | |
69 | 0 | GDALVectorAlgorithmStepRegistry::~GDALVectorAlgorithmStepRegistry() = default; |
70 | | |
71 | | /************************************************************************/ |
72 | | /* GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm() */ |
73 | | /************************************************************************/ |
74 | | |
75 | | GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm( |
76 | | const std::string &name, const std::string &description, |
77 | | const std::string &helpURL, bool standaloneStep) |
78 | 0 | : GDALVectorPipelineStepAlgorithm( |
79 | 0 | name, description, helpURL, |
80 | 0 | ConstructorOptions().SetStandaloneStep(standaloneStep)) |
81 | 0 | { |
82 | 0 | } |
83 | | |
84 | | /************************************************************************/ |
85 | | /* GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm() */ |
86 | | /************************************************************************/ |
87 | | |
88 | | GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm( |
89 | | const std::string &name, const std::string &description, |
90 | | const std::string &helpURL, const ConstructorOptions &options) |
91 | 0 | : GDALPipelineStepAlgorithm(name, description, helpURL, options) |
92 | 0 | { |
93 | 0 | if (m_standaloneStep) |
94 | 0 | { |
95 | 0 | m_supportsStreamedOutput = true; |
96 | |
|
97 | 0 | if (m_constructorOptions.addDefaultArguments) |
98 | 0 | { |
99 | 0 | AddVectorInputArgs(false); |
100 | 0 | AddProgressArg(); |
101 | 0 | AddVectorOutputArgs(false, false); |
102 | 0 | } |
103 | 0 | } |
104 | 0 | else |
105 | 0 | { |
106 | 0 | if (m_constructorOptions.addDefaultArguments) |
107 | 0 | { |
108 | 0 | AddVectorHiddenInputDatasetArg(); |
109 | 0 | } |
110 | 0 | } |
111 | 0 | } |
112 | | |
113 | 0 | GDALVectorPipelineStepAlgorithm::~GDALVectorPipelineStepAlgorithm() = default; |
114 | | |
115 | | /************************************************************************/ |
116 | | /* GDALVectorPipelineAlgorithm::GDALVectorPipelineAlgorithm() */ |
117 | | /************************************************************************/ |
118 | | |
119 | | GDALVectorPipelineAlgorithm::GDALVectorPipelineAlgorithm() |
120 | 0 | : GDALAbstractPipelineAlgorithm( |
121 | 0 | NAME, DESCRIPTION, HELP_URL, |
122 | 0 | ConstructorOptions().SetInputDatasetMaxCount(INT_MAX)) |
123 | 0 | { |
124 | 0 | m_supportsStreamedOutput = true; |
125 | |
|
126 | 0 | AddVectorInputArgs(/* hiddenForCLI = */ true); |
127 | 0 | AddProgressArg(); |
128 | 0 | AddArg("pipeline", 0, _("Pipeline string"), &m_pipeline) |
129 | 0 | .SetHiddenForCLI() |
130 | 0 | .SetPositional(); |
131 | 0 | AddVectorOutputArgs(/* hiddenForCLI = */ true, |
132 | 0 | /* shortNameOutputLayerAllowed=*/false); |
133 | |
|
134 | 0 | AddOutputStringArg(&m_output).SetHiddenForCLI(); |
135 | 0 | AddStdoutArg(&m_stdout); |
136 | |
|
137 | 0 | RegisterAlgorithms(m_stepRegistry, false); |
138 | 0 | } |
139 | | |
140 | | /************************************************************************/ |
141 | | /* GDALVectorPipelineAlgorithm::RegisterAlgorithms() */ |
142 | | /************************************************************************/ |
143 | | |
144 | | /* static */ |
145 | | void GDALVectorPipelineAlgorithm::RegisterAlgorithms( |
146 | | GDALVectorAlgorithmStepRegistry ®istry, bool forMixedPipeline) |
147 | 0 | { |
148 | 0 | GDALAlgorithmRegistry::AlgInfo algInfo; |
149 | |
|
150 | 0 | const auto addSuffixIfNeeded = |
151 | 0 | [forMixedPipeline](const char *name) -> std::string |
152 | 0 | { |
153 | 0 | return forMixedPipeline ? std::string(name).append(VECTOR_SUFFIX) |
154 | 0 | : std::string(name); |
155 | 0 | }; |
156 | |
|
157 | 0 | registry.Register<GDALVectorReadAlgorithm>( |
158 | 0 | addSuffixIfNeeded(GDALVectorReadAlgorithm::NAME)); |
159 | |
|
160 | 0 | registry.Register<GDALVectorWriteAlgorithm>( |
161 | 0 | addSuffixIfNeeded(GDALVectorWriteAlgorithm::NAME)); |
162 | |
|
163 | 0 | registry.Register<GDALVectorInfoAlgorithm>( |
164 | 0 | addSuffixIfNeeded(GDALVectorInfoAlgorithm::NAME)); |
165 | |
|
166 | 0 | registry.Register<GDALVectorBufferAlgorithm>(); |
167 | 0 | registry.Register<GDALVectorCheckCoverageAlgorithm>(); |
168 | 0 | registry.Register<GDALVectorCheckGeometryAlgorithm>(); |
169 | 0 | registry.Register<GDALVectorCombineAlgorithm>(); |
170 | |
|
171 | 0 | registry.Register<GDALVectorCompareAlgorithm>( |
172 | 0 | addSuffixIfNeeded(GDALVectorCompareAlgorithm::NAME)); |
173 | |
|
174 | 0 | registry.Register<GDALVectorConcatAlgorithm>(); |
175 | 0 | registry.Register<GDALVectorConcaveHullAlgorithm>(); |
176 | 0 | registry.Register<GDALVectorConvexHullAlgorithm>(); |
177 | 0 | registry.Register<GDALVectorCleanCoverageAlgorithm>(); |
178 | |
|
179 | 0 | registry.Register<GDALVectorClipAlgorithm>( |
180 | 0 | addSuffixIfNeeded(GDALVectorClipAlgorithm::NAME)); |
181 | 0 | registry.Register<GDALVectorDissolveAlgorithm>(); |
182 | |
|
183 | 0 | registry.Register<GDALVectorCreateAlgorithm>( |
184 | 0 | addSuffixIfNeeded(GDALVectorCreateAlgorithm::NAME)); |
185 | |
|
186 | 0 | registry.Register<GDALVectorEditAlgorithm>( |
187 | 0 | addSuffixIfNeeded(GDALVectorEditAlgorithm::NAME)); |
188 | |
|
189 | 0 | registry.Register<GDALVectorExplodeAlgorithm>(); |
190 | 0 | registry.Register<GDALVectorExplodeCollectionsAlgorithm>(); |
191 | 0 | registry.Register<GDALVectorExportSchemaAlgorithm>(); |
192 | |
|
193 | 0 | registry.Register<GDALMaterializeVectorAlgorithm>( |
194 | 0 | addSuffixIfNeeded(GDALMaterializeVectorAlgorithm::NAME)); |
195 | |
|
196 | 0 | registry.Register<GDALVectorReprojectAlgorithm>( |
197 | 0 | addSuffixIfNeeded(GDALVectorReprojectAlgorithm::NAME)); |
198 | |
|
199 | 0 | registry.Register<GDALVectorFilterAlgorithm>(); |
200 | 0 | registry.Register<GDALVectorLayerAlgebraAlgorithm>(); |
201 | 0 | registry.Register<GDALVectorLimitAlgorithm>(); |
202 | 0 | registry.Register<GDALVectorMakePointAlgorithm>(); |
203 | 0 | registry.Register<GDALVectorMakeValidAlgorithm>(); |
204 | 0 | registry.Register<GDALVectorPartitionAlgorithm>(); |
205 | 0 | registry.Register<GDALVectorRenameLayerAlgorithm>(); |
206 | 0 | registry.Register<GDALVectorSegmentizeAlgorithm>(); |
207 | |
|
208 | 0 | registry.Register<GDALVectorSelectAlgorithm>( |
209 | 0 | addSuffixIfNeeded(GDALVectorSelectAlgorithm::NAME)); |
210 | |
|
211 | 0 | registry.Register<GDALVectorSetFieldTypeAlgorithm>(); |
212 | 0 | registry.Register<GDALVectorSetGeomTypeAlgorithm>(); |
213 | 0 | registry.Register<GDALVectorSimplifyAlgorithm>(); |
214 | 0 | registry.Register<GDALVectorSimplifyCoverageAlgorithm>(); |
215 | 0 | registry.Register<GDALVectorSortAlgorithm>(); |
216 | 0 | registry.Register<GDALVectorSQLAlgorithm>(); |
217 | 0 | registry.Register<GDALVectorUpdateAlgorithm>( |
218 | 0 | addSuffixIfNeeded(GDALVectorUpdateAlgorithm::NAME)); |
219 | 0 | registry.Register<GDALVectorSwapXYAlgorithm>(); |
220 | |
|
221 | 0 | registry.Register<GDALTeeVectorAlgorithm>( |
222 | 0 | addSuffixIfNeeded(GDALTeeVectorAlgorithm::NAME)); |
223 | |
|
224 | 0 | if (!forMixedPipeline) |
225 | 0 | { |
226 | 0 | registry.Register<GDALExternalVectorAlgorithm>(); |
227 | 0 | } |
228 | 0 | } |
229 | | |
230 | | /************************************************************************/ |
231 | | /* GDALVectorPipelineAlgorithm::GetUsageForCLI() */ |
232 | | /************************************************************************/ |
233 | | |
234 | | std::string GDALVectorPipelineAlgorithm::GetUsageForCLI( |
235 | | bool shortUsage, const UsageOptions &usageOptions) const |
236 | 0 | { |
237 | 0 | UsageOptions stepUsageOptions; |
238 | 0 | stepUsageOptions.isPipelineStep = true; |
239 | |
|
240 | 0 | if (!m_helpDocCategory.empty() && m_helpDocCategory != "main") |
241 | 0 | { |
242 | 0 | auto alg = GetStepAlg(m_helpDocCategory); |
243 | 0 | if (alg) |
244 | 0 | { |
245 | 0 | alg->SetCallPath({m_helpDocCategory}); |
246 | 0 | alg->GetArg("help-doc")->Set(true); |
247 | 0 | return alg->GetUsageForCLI(shortUsage, stepUsageOptions); |
248 | 0 | } |
249 | 0 | else |
250 | 0 | { |
251 | 0 | fprintf(stderr, "ERROR: unknown pipeline step '%s'\n", |
252 | 0 | m_helpDocCategory.c_str()); |
253 | 0 | return CPLSPrintf("ERROR: unknown pipeline step '%s'\n", |
254 | 0 | m_helpDocCategory.c_str()); |
255 | 0 | } |
256 | 0 | } |
257 | | |
258 | 0 | UsageOptions usageOptionsMain(usageOptions); |
259 | 0 | usageOptionsMain.isPipelineMain = true; |
260 | 0 | std::string ret = |
261 | 0 | GDALAlgorithm::GetUsageForCLI(shortUsage, usageOptionsMain); |
262 | 0 | if (shortUsage) |
263 | 0 | return ret; |
264 | | |
265 | 0 | ret += "\n<PIPELINE> is of the form: read|concat [READ-OPTIONS] " |
266 | 0 | "( ! <STEP-NAME> [STEP-OPTIONS] )* ! write|info [WRITE-OPTIONS]\n"; |
267 | |
|
268 | 0 | if (m_helpDocCategory == "main") |
269 | 0 | { |
270 | 0 | return ret; |
271 | 0 | } |
272 | | |
273 | 0 | ret += '\n'; |
274 | 0 | ret += "Example: 'gdal vector pipeline --progress ! read in.gpkg ! \\\n"; |
275 | 0 | ret += " reproject --output-crs=EPSG:32632 ! "; |
276 | 0 | ret += "write out.gpkg --overwrite'\n"; |
277 | 0 | ret += '\n'; |
278 | 0 | ret += "Potential steps are:\n"; |
279 | |
|
280 | 0 | for (const std::string &name : m_stepRegistry.GetNames()) |
281 | 0 | { |
282 | 0 | auto alg = GetStepAlg(name); |
283 | 0 | assert(alg); |
284 | 0 | auto [options, maxOptLen] = alg->GetArgNamesForCLI(); |
285 | 0 | stepUsageOptions.maxOptLen = |
286 | 0 | std::max(stepUsageOptions.maxOptLen, maxOptLen); |
287 | 0 | } |
288 | | |
289 | 0 | { |
290 | 0 | const auto name = GDALVectorReadAlgorithm::NAME; |
291 | 0 | ret += '\n'; |
292 | 0 | auto alg = GetStepAlg(name); |
293 | 0 | alg->SetCallPath({name}); |
294 | 0 | ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions); |
295 | 0 | } |
296 | 0 | for (const std::string &name : m_stepRegistry.GetNames()) |
297 | 0 | { |
298 | 0 | auto alg = GetStepAlg(name); |
299 | 0 | assert(alg); |
300 | 0 | if (alg->CanBeFirstStep() && !alg->CanBeMiddleStep() && |
301 | 0 | !alg->IsHidden() && name != GDALVectorReadAlgorithm::NAME) |
302 | 0 | { |
303 | 0 | ret += '\n'; |
304 | 0 | alg->SetCallPath({name}); |
305 | 0 | ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions); |
306 | 0 | } |
307 | 0 | } |
308 | 0 | for (const std::string &name : m_stepRegistry.GetNames()) |
309 | 0 | { |
310 | 0 | auto alg = GetStepAlg(name); |
311 | 0 | assert(alg); |
312 | 0 | if (alg->CanBeMiddleStep() && !alg->IsHidden()) |
313 | 0 | { |
314 | 0 | ret += '\n'; |
315 | 0 | alg->SetCallPath({name}); |
316 | 0 | ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions); |
317 | 0 | } |
318 | 0 | } |
319 | 0 | for (const std::string &name : m_stepRegistry.GetNames()) |
320 | 0 | { |
321 | 0 | auto alg = GetStepAlg(name); |
322 | 0 | assert(alg); |
323 | 0 | if (alg->CanBeLastStep() && !alg->CanBeMiddleStep() && |
324 | 0 | !alg->IsHidden() && name != GDALVectorWriteAlgorithm::NAME) |
325 | 0 | { |
326 | 0 | ret += '\n'; |
327 | 0 | alg->SetCallPath({name}); |
328 | 0 | ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions); |
329 | 0 | } |
330 | 0 | } |
331 | 0 | { |
332 | 0 | const auto name = GDALVectorWriteAlgorithm::NAME; |
333 | 0 | ret += '\n'; |
334 | 0 | auto alg = GetStepAlg(name); |
335 | 0 | alg->SetCallPath({name}); |
336 | 0 | ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions); |
337 | 0 | } |
338 | |
|
339 | 0 | ret += GetUsageForCLIEnd(); |
340 | |
|
341 | 0 | return ret; |
342 | 0 | } |
343 | | |
344 | | /************************************************************************/ |
345 | | /* GDALVectorDecoratedDataset */ |
346 | | /************************************************************************/ |
347 | | |
348 | | namespace |
349 | | { |
350 | | class DummyDataset final : public GDALDataset |
351 | | { |
352 | | public: |
353 | 0 | DummyDataset() = default; |
354 | | }; |
355 | | } // namespace |
356 | | |
357 | | /************************************************************************/ |
358 | | /* GDALVectorDecoratedDataset() */ |
359 | | /************************************************************************/ |
360 | | |
361 | | GDALVectorDecoratedDataset::GDALVectorDecoratedDataset(GDALDataset *poSrcDS) |
362 | 0 | : m_dummySrcDS(poSrcDS ? nullptr : std::make_unique<DummyDataset>()), |
363 | 0 | m_srcDS(poSrcDS ? *poSrcDS : *(m_dummySrcDS.get())) |
364 | 0 | { |
365 | 0 | m_srcDS.Reference(); |
366 | 0 | SetDescription(m_srcDS.GetDescription()); |
367 | 0 | } |
368 | | |
369 | | /************************************************************************/ |
370 | | /* ~GDALVectorDecoratedDataset() */ |
371 | | /************************************************************************/ |
372 | | |
373 | | GDALVectorDecoratedDataset::~GDALVectorDecoratedDataset() |
374 | 0 | { |
375 | 0 | m_srcDS.ReleaseRef(); |
376 | 0 | } |
377 | | |
378 | | /************************************************************************/ |
379 | | /* GDALVectorPipelineOutputLayer */ |
380 | | /************************************************************************/ |
381 | | |
382 | | /************************************************************************/ |
383 | | /* GDALVectorPipelineOutputLayer() */ |
384 | | /************************************************************************/ |
385 | | |
386 | | GDALVectorPipelineOutputLayer::GDALVectorPipelineOutputLayer(OGRLayer &srcLayer) |
387 | 0 | : m_srcLayer(srcLayer) |
388 | 0 | { |
389 | 0 | } |
390 | | |
391 | | /************************************************************************/ |
392 | | /* ~GDALVectorPipelineOutputLayer() */ |
393 | | /************************************************************************/ |
394 | | |
395 | 0 | GDALVectorPipelineOutputLayer::~GDALVectorPipelineOutputLayer() = default; |
396 | | |
397 | | /************************************************************************/ |
398 | | /* GDALVectorPipelineOutputLayer::ResetReading() */ |
399 | | /************************************************************************/ |
400 | | |
401 | | void GDALVectorPipelineOutputLayer::ResetReading() |
402 | 0 | { |
403 | 0 | m_srcLayer.ResetReading(); |
404 | 0 | m_pendingFeatures.clear(); |
405 | 0 | m_idxInPendingFeatures = 0; |
406 | 0 | } |
407 | | |
408 | | /************************************************************************/ |
409 | | /* GDALVectorPipelineOutputLayer::GetNextFeature() */ |
410 | | /************************************************************************/ |
411 | | |
412 | | OGRFeature *GDALVectorPipelineOutputLayer::GetNextFeature() |
413 | 0 | { |
414 | 0 | if (m_idxInPendingFeatures < m_pendingFeatures.size()) |
415 | 0 | { |
416 | 0 | OGRFeature *poFeature = |
417 | 0 | m_pendingFeatures[m_idxInPendingFeatures].release(); |
418 | 0 | ++m_idxInPendingFeatures; |
419 | 0 | return poFeature; |
420 | 0 | } |
421 | 0 | m_pendingFeatures.clear(); |
422 | 0 | m_idxInPendingFeatures = 0; |
423 | 0 | while (true) |
424 | 0 | { |
425 | 0 | auto poSrcFeature = |
426 | 0 | std::unique_ptr<OGRFeature>(m_srcLayer.GetNextFeature()); |
427 | 0 | if (!poSrcFeature) |
428 | 0 | return nullptr; |
429 | | // It is the job of TranslateFeature() to apply layer filters |
430 | 0 | if (!TranslateFeature(std::move(poSrcFeature), m_pendingFeatures)) |
431 | 0 | { |
432 | 0 | return nullptr; |
433 | 0 | } |
434 | 0 | if (!m_pendingFeatures.empty()) |
435 | 0 | break; |
436 | 0 | } |
437 | 0 | OGRFeature *poFeature = m_pendingFeatures[0].release(); |
438 | 0 | m_idxInPendingFeatures = 1; |
439 | 0 | return poFeature; |
440 | 0 | } |
441 | | |
442 | | /************************************************************************/ |
443 | | /* GDALVectorPipelineOutputLayer::PassesFilters() */ |
444 | | /************************************************************************/ |
445 | | |
446 | | bool GDALVectorPipelineOutputLayer::PassesFilters(const OGRFeature *poFeature) |
447 | 0 | { |
448 | 0 | return (!m_poFilterGeom || FilterGeometry(poFeature->GetGeometryRef())) && |
449 | 0 | (!m_poAttrQuery || m_poAttrQuery->Evaluate(poFeature)); |
450 | 0 | } |
451 | | |
452 | | /************************************************************************/ |
453 | | /* GDALVectorOutputDataset */ |
454 | | /************************************************************************/ |
455 | | |
456 | | /************************************************************************/ |
457 | | /* GDALVectorOutputDataset() */ |
458 | | /************************************************************************/ |
459 | | |
460 | | GDALVectorOutputDataset::GDALVectorOutputDataset(GDALDataset *poSrcDS) |
461 | 0 | : GDALVectorDecoratedDataset(poSrcDS) |
462 | 0 | { |
463 | 0 | } |
464 | | |
465 | | /************************************************************************/ |
466 | | /* TestCapability() */ |
467 | | /************************************************************************/ |
468 | | |
469 | | bool GDALVectorOutputDataset::TestCapability(const char *) const |
470 | 0 | { |
471 | 0 | return 0; |
472 | 0 | } |
473 | | |
474 | | /************************************************************************/ |
475 | | /* GDALVectorPipelineOutputDataset */ |
476 | | /************************************************************************/ |
477 | | |
478 | | /************************************************************************/ |
479 | | /* GDALVectorPipelineOutputDataset() */ |
480 | | /************************************************************************/ |
481 | | |
482 | | GDALVectorPipelineOutputDataset::GDALVectorPipelineOutputDataset( |
483 | | GDALDataset &srcDS) |
484 | 0 | : GDALVectorDecoratedDataset(&srcDS) |
485 | 0 | { |
486 | 0 | } |
487 | | |
488 | | /************************************************************************/ |
489 | | /* GDALVectorPipelineOutputDataset::AddLayer() */ |
490 | | /************************************************************************/ |
491 | | |
492 | | void GDALVectorPipelineOutputDataset::AddLayer( |
493 | | OGRLayer &oSrcLayer, |
494 | | std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer) |
495 | 0 | { |
496 | 0 | m_layersToDestroy.push_back(std::move(poNewLayer)); |
497 | 0 | OGRLayerWithTranslateFeature *poNewLayerRaw = |
498 | 0 | m_layersToDestroy.back().get(); |
499 | 0 | m_layers.push_back(poNewLayerRaw); |
500 | 0 | m_mapSrcLayerToNewLayer[&oSrcLayer] = poNewLayerRaw; |
501 | 0 | } |
502 | | |
503 | | /************************************************************************/ |
504 | | /* GDALVectorPipelineOutputDataset::GetLayerCount() */ |
505 | | /************************************************************************/ |
506 | | |
507 | | int GDALVectorPipelineOutputDataset::GetLayerCount() const |
508 | 0 | { |
509 | 0 | return static_cast<int>(m_layers.size()); |
510 | 0 | } |
511 | | |
512 | | /************************************************************************/ |
513 | | /* GDALVectorPipelineOutputDataset::GetLayer() */ |
514 | | /************************************************************************/ |
515 | | |
516 | | OGRLayer *GDALVectorPipelineOutputDataset::GetLayer(int idx) const |
517 | 0 | { |
518 | 0 | return idx >= 0 && idx < GetLayerCount() ? m_layers[idx] : nullptr; |
519 | 0 | } |
520 | | |
521 | | /************************************************************************/ |
522 | | /* GDALVectorPipelineOutputDataset::TestCapability() */ |
523 | | /************************************************************************/ |
524 | | |
525 | | bool GDALVectorPipelineOutputDataset::TestCapability(const char *pszCap) const |
526 | 0 | { |
527 | 0 | if (EQUAL(pszCap, ODsCRandomLayerRead) || |
528 | 0 | EQUAL(pszCap, ODsCMeasuredGeometries) || EQUAL(pszCap, ODsCZGeometries)) |
529 | 0 | { |
530 | 0 | return m_srcDS.TestCapability(pszCap); |
531 | 0 | } |
532 | 0 | return false; |
533 | 0 | } |
534 | | |
535 | | /************************************************************************/ |
536 | | /* GDALVectorPipelineOutputDataset::ResetReading() */ |
537 | | /************************************************************************/ |
538 | | |
539 | | void GDALVectorPipelineOutputDataset::ResetReading() |
540 | 0 | { |
541 | 0 | m_srcDS.ResetReading(); |
542 | 0 | m_pendingFeatures.clear(); |
543 | 0 | m_idxInPendingFeatures = 0; |
544 | 0 | } |
545 | | |
546 | | /************************************************************************/ |
547 | | /* GDALVectorPipelineOutputDataset::GetNextFeature() */ |
548 | | /************************************************************************/ |
549 | | |
550 | | OGRFeature *GDALVectorPipelineOutputDataset::GetNextFeature( |
551 | | OGRLayer **ppoBelongingLayer, double *pdfProgressPct, |
552 | | GDALProgressFunc pfnProgress, void *pProgressData) |
553 | 0 | { |
554 | 0 | if (m_idxInPendingFeatures < m_pendingFeatures.size()) |
555 | 0 | { |
556 | 0 | OGRFeature *poFeature = |
557 | 0 | m_pendingFeatures[m_idxInPendingFeatures].release(); |
558 | 0 | if (ppoBelongingLayer) |
559 | 0 | *ppoBelongingLayer = m_belongingLayer; |
560 | 0 | ++m_idxInPendingFeatures; |
561 | 0 | return poFeature; |
562 | 0 | } |
563 | | |
564 | 0 | m_pendingFeatures.clear(); |
565 | 0 | m_idxInPendingFeatures = 0; |
566 | |
|
567 | 0 | while (true) |
568 | 0 | { |
569 | 0 | OGRLayer *poSrcBelongingLayer = nullptr; |
570 | 0 | auto poSrcFeature = std::unique_ptr<OGRFeature>(m_srcDS.GetNextFeature( |
571 | 0 | &poSrcBelongingLayer, pdfProgressPct, pfnProgress, pProgressData)); |
572 | 0 | if (!poSrcFeature) |
573 | 0 | return nullptr; |
574 | 0 | auto iterToDstLayer = m_mapSrcLayerToNewLayer.find(poSrcBelongingLayer); |
575 | 0 | if (iterToDstLayer != m_mapSrcLayerToNewLayer.end()) |
576 | 0 | { |
577 | 0 | m_belongingLayer = iterToDstLayer->second; |
578 | |
|
579 | 0 | if (!m_belongingLayer->TranslateFeature(std::move(poSrcFeature), |
580 | 0 | m_pendingFeatures)) |
581 | 0 | { |
582 | 0 | return nullptr; |
583 | 0 | } |
584 | | |
585 | 0 | if (!m_pendingFeatures.empty()) |
586 | 0 | break; |
587 | 0 | } |
588 | 0 | } |
589 | 0 | OGRFeature *poFeature = m_pendingFeatures[0].release(); |
590 | 0 | if (ppoBelongingLayer) |
591 | 0 | *ppoBelongingLayer = m_belongingLayer; |
592 | 0 | m_idxInPendingFeatures = 1; |
593 | 0 | return poFeature; |
594 | 0 | } |
595 | | |
596 | | /************************************************************************/ |
597 | | /* GDALVectorPipelinePassthroughLayer::GetLayerDefn() */ |
598 | | /************************************************************************/ |
599 | | |
600 | | const OGRFeatureDefn *GDALVectorPipelinePassthroughLayer::GetLayerDefn() const |
601 | 0 | { |
602 | 0 | return m_srcLayer.GetLayerDefn(); |
603 | 0 | } |
604 | | |
605 | | /************************************************************************/ |
606 | | /* GDALVectorPipelinePassthroughLayer::GetLayerDefn() */ |
607 | | /************************************************************************/ |
608 | | |
609 | | bool GDALVectorPipelinePassthroughLayer::TranslateFeature( |
610 | | std::unique_ptr<OGRFeature> poSrcFeature, |
611 | | std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) |
612 | 0 | { |
613 | 0 | if (PassesFilters(poSrcFeature.get())) |
614 | 0 | { |
615 | 0 | apoOutFeatures.push_back(std::move(poSrcFeature)); |
616 | 0 | } |
617 | |
|
618 | 0 | return true; |
619 | 0 | } |
620 | | |
621 | | /************************************************************************/ |
622 | | /* GDALVectorNonStreamingAlgorithmDataset() */ |
623 | | /************************************************************************/ |
624 | | |
625 | | GDALVectorNonStreamingAlgorithmDataset::GDALVectorNonStreamingAlgorithmDataset( |
626 | | GDALDataset &oSrcDS) |
627 | 0 | : GDALVectorDecoratedDataset(&oSrcDS) |
628 | 0 | { |
629 | 0 | } |
630 | | |
631 | | /************************************************************************/ |
632 | | /* ~GDALVectorNonStreamingAlgorithmDataset() */ |
633 | | /************************************************************************/ |
634 | | |
635 | | GDALVectorNonStreamingAlgorithmDataset:: |
636 | 0 | ~GDALVectorNonStreamingAlgorithmDataset() = default; |
637 | | |
638 | | /************************************************************************/ |
639 | | /* GDALVectorNonStreamingAlgorithmDataset::AddProcessedLayer() */ |
640 | | /************************************************************************/ |
641 | | |
642 | | bool GDALVectorNonStreamingAlgorithmDataset::AddProcessedLayer( |
643 | | std::unique_ptr<GDALVectorNonStreamingAlgorithmLayer> layer, |
644 | | GDALProgressFunc progressFn, void *progressData) |
645 | 0 | { |
646 | 0 | if (!layer->Process(progressFn, progressData)) |
647 | 0 | { |
648 | 0 | return false; |
649 | 0 | } |
650 | | |
651 | 0 | m_owned_layers.emplace_back(std::move(layer)); |
652 | 0 | m_layers.push_back(m_owned_layers.back().get()); |
653 | |
|
654 | 0 | return true; |
655 | 0 | } |
656 | | |
657 | | /************************************************************************/ |
658 | | /* GDALVectorNonStreamingAlgorithmDataset::AddPassThroughLayer() */ |
659 | | /************************************************************************/ |
660 | | |
661 | | void GDALVectorNonStreamingAlgorithmDataset::AddPassThroughLayer( |
662 | | OGRLayer &oLayer) |
663 | 0 | { |
664 | 0 | m_owned_layers.push_back( |
665 | 0 | std::make_unique<GDALVectorPipelinePassthroughLayer>(oLayer)); |
666 | 0 | m_layers.push_back(m_owned_layers.back().get()); |
667 | 0 | } |
668 | | |
669 | | /************************************************************************/ |
670 | | /* GDALVectorNonStreamingAlgorithmDataset::GetLayerCount() */ |
671 | | /************************************************************************/ |
672 | | |
673 | | int GDALVectorNonStreamingAlgorithmDataset::GetLayerCount() const |
674 | 0 | { |
675 | 0 | return static_cast<int>(m_layers.size()); |
676 | 0 | } |
677 | | |
678 | | /************************************************************************/ |
679 | | /* GDALVectorNonStreamingAlgorithmDataset::GetLayer() */ |
680 | | /************************************************************************/ |
681 | | |
682 | | OGRLayer *GDALVectorNonStreamingAlgorithmDataset::GetLayer(int idx) const |
683 | 0 | { |
684 | 0 | if (idx < 0 || idx >= static_cast<int>(m_layers.size())) |
685 | 0 | { |
686 | 0 | return nullptr; |
687 | 0 | } |
688 | 0 | return m_layers[idx]; |
689 | 0 | } |
690 | | |
691 | | /************************************************************************/ |
692 | | /* GDALVectorNonStreamingAlgorithmDataset::TestCapability() */ |
693 | | /************************************************************************/ |
694 | | |
695 | | bool GDALVectorNonStreamingAlgorithmDataset::TestCapability( |
696 | | const char *pszCap) const |
697 | 0 | { |
698 | 0 | if (EQUAL(pszCap, ODsCCurveGeometries) || |
699 | 0 | EQUAL(pszCap, ODsCMeasuredGeometries) || EQUAL(pszCap, ODsCZGeometries)) |
700 | 0 | { |
701 | 0 | return true; |
702 | 0 | } |
703 | | |
704 | 0 | return false; |
705 | 0 | } |
706 | | |
707 | | /************************************************************************/ |
708 | | /* GDALVectorAlgorithmLayerProgressHelper() */ |
709 | | /************************************************************************/ |
710 | | |
711 | | GDALVectorAlgorithmLayerProgressHelper::GDALVectorAlgorithmLayerProgressHelper( |
712 | | GDALProgressFunc pfnProgress, void *pProgressData) |
713 | 0 | : m_pfnProgress(pfnProgress), m_pProgressData(pProgressData) |
714 | 0 | { |
715 | 0 | } |
716 | | |
717 | | /************************************************************************/ |
718 | | /* GDALVectorAlgorithmLayerProgressHelper() */ |
719 | | /************************************************************************/ |
720 | | |
721 | | GDALVectorAlgorithmLayerProgressHelper::GDALVectorAlgorithmLayerProgressHelper( |
722 | | const GDALPipelineStepRunContext &ctxt) |
723 | 0 | : GDALVectorAlgorithmLayerProgressHelper(ctxt.m_pfnProgress, |
724 | 0 | ctxt.m_pProgressData) |
725 | 0 | { |
726 | 0 | } |
727 | | |
728 | | /************************************************************************/ |
729 | | /* GDALVectorAlgorithmLayerProgressHelper::AddProcessedLayer() */ |
730 | | /************************************************************************/ |
731 | | |
732 | | void GDALVectorAlgorithmLayerProgressHelper::AddProcessedLayer( |
733 | | OGRLayer &srcLayer) |
734 | 0 | { |
735 | 0 | m_apoSrcLayers.emplace_back(&srcLayer, true); |
736 | 0 | if (m_pfnProgress && m_nTotalFeatures >= 0 && |
737 | 0 | srcLayer.TestCapability(OLCFastFeatureCount)) |
738 | 0 | { |
739 | 0 | const auto nLayerFeatures = srcLayer.GetFeatureCount(false); |
740 | 0 | if (nLayerFeatures < 0) |
741 | 0 | m_nTotalFeatures = -1; |
742 | 0 | else |
743 | 0 | m_nTotalFeatures += nLayerFeatures; |
744 | 0 | m_anFeatures.push_back(nLayerFeatures); |
745 | 0 | } |
746 | 0 | else |
747 | 0 | { |
748 | 0 | m_anFeatures.push_back(-1); |
749 | 0 | m_nTotalFeatures = -1; |
750 | 0 | } |
751 | 0 | } |
752 | | |
753 | | /************************************************************************/ |
754 | | /* GDALVectorAlgorithmLayerProgressHelper::AddPassThroughLayer() */ |
755 | | /************************************************************************/ |
756 | | |
757 | | void GDALVectorAlgorithmLayerProgressHelper::AddPassThroughLayer( |
758 | | OGRLayer &srcLayer) |
759 | 0 | { |
760 | 0 | m_apoSrcLayers.emplace_back(&srcLayer, false); |
761 | 0 | } |
762 | | |
763 | | /************************************************************************/ |
764 | | /* GDALVectorNonStreamingAlgorithmLayer() */ |
765 | | /************************************************************************/ |
766 | | |
767 | | GDALVectorNonStreamingAlgorithmLayer::GDALVectorNonStreamingAlgorithmLayer( |
768 | | OGRLayer &srcLayer, int geomFieldIndex) |
769 | 0 | : m_srcLayer(srcLayer), m_geomFieldIndex(geomFieldIndex) |
770 | 0 | { |
771 | 0 | } |
772 | | |
773 | | /************************************************************************/ |
774 | | /* ~GDALVectorNonStreamingAlgorithmLayer() */ |
775 | | /************************************************************************/ |
776 | | |
777 | 0 | GDALVectorNonStreamingAlgorithmLayer::~GDALVectorNonStreamingAlgorithmLayer() = |
778 | | default; |
779 | | |
780 | | /************************************************************************/ |
781 | | /* GDALVectorNonStreamingAlgorithmLayer::GetNextRawFeature() */ |
782 | | /************************************************************************/ |
783 | | |
784 | | OGRFeature *GDALVectorNonStreamingAlgorithmLayer::GetNextRawFeature() |
785 | 0 | { |
786 | 0 | return GetNextProcessedFeature().release(); |
787 | 0 | } |
788 | | |
789 | | /************************************************************************/ |
790 | | /* GDALVectorAlgorithmLayerProgressHelper::iterator::operator*() */ |
791 | | /************************************************************************/ |
792 | | |
793 | | GDALVectorAlgorithmLayerProgressHelper::iterator::value_type |
794 | | GDALVectorAlgorithmLayerProgressHelper::iterator::operator*() const |
795 | 0 | { |
796 | 0 | const double dfProgressStart = |
797 | 0 | m_helper.m_anFeatures.empty() ? 0 |
798 | 0 | : m_helper.m_nTotalFeatures > 0 |
799 | 0 | ? static_cast<double>(m_nFeatureIdx) / |
800 | 0 | static_cast<double>(m_helper.m_nTotalFeatures) |
801 | 0 | : static_cast<double>(m_nProcessedLayerIdx) / |
802 | 0 | std::max(1.0, |
803 | 0 | static_cast<double>(m_helper.m_anFeatures.size())); |
804 | 0 | const double dfProgressEnd = |
805 | 0 | m_helper.m_anFeatures.empty() ? 0 |
806 | 0 | : m_helper.m_nTotalFeatures > 0 |
807 | 0 | ? static_cast<double>(m_nFeatureIdx + |
808 | 0 | m_helper.m_anFeatures[m_nProcessedLayerIdx]) / |
809 | 0 | static_cast<double>(m_helper.m_nTotalFeatures) |
810 | 0 | : static_cast<double>(m_nProcessedLayerIdx + 1) / |
811 | 0 | std::max(1.0, |
812 | 0 | static_cast<double>(m_helper.m_anFeatures.size())); |
813 | |
|
814 | 0 | progress_data_unique_ptr pScaledProgressData(nullptr, |
815 | 0 | GDALDestroyScaledProgress); |
816 | 0 | if (m_helper.m_pfnProgress && m_helper.m_apoSrcLayers[m_nLayerIdx].second) |
817 | 0 | { |
818 | 0 | pScaledProgressData.reset(GDALCreateScaledProgress( |
819 | 0 | dfProgressStart, dfProgressEnd, m_helper.m_pfnProgress, |
820 | 0 | m_helper.m_pProgressData)); |
821 | 0 | } |
822 | |
|
823 | 0 | return value_type(m_helper.m_apoSrcLayers[m_nLayerIdx].first, |
824 | 0 | m_helper.m_apoSrcLayers[m_nLayerIdx].second, |
825 | 0 | m_helper.m_pfnProgress ? GDALScaledProgress : nullptr, |
826 | 0 | std::move(pScaledProgressData)); |
827 | 0 | } |
828 | | |
829 | | //! @endcond |