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