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