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