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