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