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