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