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