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