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