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