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 : #ifndef GDALVECTORRPIPELINESTEPALGORITHM_INCLUDED
14 : #define GDALVECTORRPIPELINESTEPALGORITHM_INCLUDED
15 :
16 : #include "gdalalgorithm.h"
17 : #include "gdalpipelinestepalgorithm.h"
18 :
19 : #include "ogrsf_frmts.h"
20 : #include "ogrlayerwithtranslatefeature.h"
21 :
22 : #include <map>
23 : #include <tuple>
24 : #include <vector>
25 :
26 : //! @cond Doxygen_Suppress
27 :
28 : /************************************************************************/
29 : /* GDALVectorPipelineStepAlgorithm */
30 : /************************************************************************/
31 :
32 4908 : class GDALVectorPipelineStepAlgorithm /* non final */
33 : : public GDALPipelineStepAlgorithm
34 : {
35 : public:
36 : ~GDALVectorPipelineStepAlgorithm() override;
37 :
38 : protected:
39 : GDALVectorPipelineStepAlgorithm(const std::string &name,
40 : const std::string &description,
41 : const std::string &helpURL,
42 : bool standaloneStep);
43 :
44 : GDALVectorPipelineStepAlgorithm(const std::string &name,
45 : const std::string &description,
46 : const std::string &helpURL,
47 : const ConstructorOptions &options);
48 :
49 : friend class GDALVectorPipelineAlgorithm;
50 : friend class GDALVectorConcatAlgorithm;
51 :
52 602 : int GetInputType() const override
53 : {
54 602 : return GDAL_OF_VECTOR;
55 : }
56 :
57 531 : int GetOutputType() const override
58 : {
59 531 : return GDAL_OF_VECTOR;
60 : }
61 : };
62 :
63 : /************************************************************************/
64 : /* GDALVectorDecoratedDataset */
65 : /************************************************************************/
66 :
67 : /** Base class for GDALVectorOutputDataset, GDALVectorNonStreamingAlgorithmDataset
68 : * and GDALVectorPipelineOutputDataset
69 : */
70 : class GDALVectorDecoratedDataset /* non final */
71 : : public GDALDataset
72 : {
73 : public:
74 : ~GDALVectorDecoratedDataset() override;
75 :
76 17 : CSLConstList GetMetadata(const char *pszDomain) override
77 : {
78 17 : return m_srcDS.GetMetadata(pszDomain);
79 : }
80 :
81 13 : const char *GetMetadataItem(const char *pszName,
82 : const char *pszDomain) override
83 : {
84 13 : return m_srcDS.GetMetadataItem(pszName, pszDomain);
85 : }
86 :
87 : std::vector<std::string>
88 7 : GetFieldDomainNames(CSLConstList papszOptions) const override
89 : {
90 7 : return m_srcDS.GetFieldDomainNames(papszOptions);
91 : }
92 :
93 3 : const OGRFieldDomain *GetFieldDomain(const std::string &name) const override
94 : {
95 3 : return m_srcDS.GetFieldDomain(name);
96 : }
97 :
98 : std::vector<std::string>
99 115 : GetRelationshipNames(CSLConstList papszOptions) const override
100 : {
101 115 : return m_srcDS.GetRelationshipNames(papszOptions);
102 : }
103 :
104 : const GDALRelationship *
105 1 : GetRelationship(const std::string &name) const override
106 : {
107 1 : return m_srcDS.GetRelationship(name);
108 : }
109 :
110 : private:
111 : std::unique_ptr<GDALDataset> m_dummySrcDS{};
112 :
113 : protected:
114 : explicit GDALVectorDecoratedDataset(GDALDataset *poSrcDS);
115 :
116 : GDALDataset &m_srcDS;
117 : };
118 :
119 : /************************************************************************/
120 : /* GDALVectorOutputDataset */
121 : /************************************************************************/
122 :
123 : class GDALVectorOutputDataset final : public GDALVectorDecoratedDataset
124 : {
125 :
126 : public:
127 : explicit GDALVectorOutputDataset(GDALDataset *poSrcDS);
128 :
129 38 : int GetLayerCount() const override
130 : {
131 38 : return static_cast<int>(m_layers.size());
132 : }
133 :
134 18 : const OGRLayer *GetLayer(int idx) const override
135 : {
136 18 : return m_layers[idx].get();
137 : }
138 :
139 : int TestCapability(const char *) const override;
140 :
141 18 : void AddLayer(std::unique_ptr<OGRLayer> layer)
142 : {
143 18 : m_layers.emplace_back(std::move(layer));
144 18 : }
145 :
146 : private:
147 : std::vector<std::unique_ptr<OGRLayer>> m_layers{};
148 : };
149 :
150 : /************************************************************************/
151 : /* GDALVectorAlgorithmLayerProgressHelper */
152 : /************************************************************************/
153 :
154 : /**
155 : * This class helps doing progress report for algorithm iterating over layers
156 : * of the source dataset.
157 : */
158 : class GDALVectorAlgorithmLayerProgressHelper
159 : {
160 : public:
161 : /** Constructor */
162 : GDALVectorAlgorithmLayerProgressHelper(GDALProgressFunc pfnProgress,
163 : void *pProgressData);
164 : /** Constructor */
165 : explicit GDALVectorAlgorithmLayerProgressHelper(
166 : const GDALPipelineStepRunContext &ctxt);
167 :
168 : /** Register the passed layer as a layer that will be processed. */
169 : void AddProcessedLayer(OGRLayer &srcLayer);
170 :
171 : /** Register the passed layer as a layer that will be forwarded without
172 : * processing. */
173 : void AddPassThroughLayer(OGRLayer &srcLayer);
174 :
175 : //! @cond Doxygen_Suppress
176 : class iterator
177 : {
178 : public:
179 150 : explicit iterator(const GDALVectorAlgorithmLayerProgressHelper &helper,
180 : bool start)
181 150 : : m_helper(helper),
182 150 : m_nLayerIdx(start ? 0 : m_helper.m_apoSrcLayers.size())
183 : {
184 150 : }
185 :
186 : inline bool operator==(const iterator &other) const
187 : {
188 : return m_nLayerIdx == other.m_nLayerIdx;
189 : }
190 :
191 148 : inline bool operator!=(const iterator &other) const
192 : {
193 148 : return m_nLayerIdx != other.m_nLayerIdx;
194 : }
195 :
196 73 : inline iterator &operator++()
197 : {
198 73 : if (!m_helper.m_anFeatures.empty())
199 67 : m_nFeatureIdx += m_helper.m_anFeatures[m_nProcessedLayerIdx];
200 73 : if (m_helper.m_apoSrcLayers[m_nLayerIdx].second)
201 65 : ++m_nProcessedLayerIdx;
202 73 : ++m_nLayerIdx;
203 73 : return *this;
204 : }
205 :
206 : using progress_data_unique_ptr =
207 : std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>;
208 : using value_type = std::tuple<OGRLayer *, bool, GDALProgressFunc,
209 : progress_data_unique_ptr>;
210 :
211 : value_type operator*() const;
212 :
213 : private:
214 : const GDALVectorAlgorithmLayerProgressHelper &m_helper;
215 : size_t m_nLayerIdx = 0;
216 : size_t m_nProcessedLayerIdx = 0;
217 : GIntBig m_nFeatureIdx = 0;
218 : };
219 :
220 : //! @endcond
221 :
222 : /** Start of an iterator over layers registered with AddProcessedLayer()
223 : * and AddUnprocessedLayer() */
224 75 : iterator begin() const
225 : {
226 75 : return iterator(*this, true);
227 : }
228 :
229 : /** End of an iterator over layers registered with AddProcessedLayer()
230 : * and AddUnprocessedLayer() */
231 75 : iterator end() const
232 : {
233 75 : return iterator(*this, false);
234 : }
235 :
236 : /** Return if AddProcessedLayer() has been called at least once. */
237 4 : bool HasProcessedLayers() const
238 : {
239 4 : return !m_anFeatures.empty();
240 : }
241 :
242 : private:
243 : GDALProgressFunc m_pfnProgress = nullptr;
244 : void *m_pProgressData = nullptr;
245 : int64_t m_nTotalFeatures = 0;
246 : std::vector<std::pair<OGRLayer *, bool>> m_apoSrcLayers{};
247 : std::vector<int64_t> m_anFeatures{};
248 :
249 : CPL_DISALLOW_COPY_ASSIGN(GDALVectorAlgorithmLayerProgressHelper)
250 : };
251 :
252 : /************************************************************************/
253 : /* GDALVectorPipelineOutputLayer */
254 : /************************************************************************/
255 :
256 : /** Class that implements GetNextFeature() by forwarding to
257 : * OGRLayerWithTranslateFeature::TranslateFeature() implementation, which
258 : * might return several features.
259 : */
260 306 : class GDALVectorPipelineOutputLayer /* non final */
261 : : public OGRLayerWithTranslateFeature,
262 : public OGRGetNextFeatureThroughRaw<GDALVectorPipelineOutputLayer>
263 : {
264 : protected:
265 : explicit GDALVectorPipelineOutputLayer(OGRLayer &oSrcLayer);
266 : ~GDALVectorPipelineOutputLayer() override;
267 :
268 4801 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorPipelineOutputLayer)
269 :
270 : OGRLayer &m_srcLayer;
271 :
272 7 : void FailTranslation()
273 : {
274 7 : m_translateError = true;
275 7 : }
276 :
277 : public:
278 : void ResetReading() override;
279 : OGRFeature *GetNextRawFeature();
280 :
281 : private:
282 : std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
283 : size_t m_idxInPendingFeatures = 0;
284 : bool m_translateError = false;
285 : };
286 :
287 : /************************************************************************/
288 : /* GDALVectorPipelinePassthroughLayer */
289 : /************************************************************************/
290 :
291 : /** Class that forwards GetNextFeature() calls to the source layer and
292 : * can be added to GDALVectorPipelineOutputDataset::AddLayer()
293 : */
294 : class GDALVectorPipelinePassthroughLayer /* non final */
295 : : public GDALVectorPipelineOutputLayer
296 : {
297 : public:
298 68 : explicit GDALVectorPipelinePassthroughLayer(OGRLayer &oSrcLayer)
299 68 : : GDALVectorPipelineOutputLayer(oSrcLayer)
300 : {
301 68 : GDALVectorPipelinePassthroughLayer::SetDescription(
302 68 : oSrcLayer.GetDescription());
303 68 : }
304 :
305 : const OGRFeatureDefn *GetLayerDefn() const override;
306 :
307 278 : int TestCapability(const char *pszCap) const override
308 : {
309 278 : if (EQUAL(pszCap, OLCFastFeatureCount))
310 0 : return false;
311 278 : return m_srcLayer.TestCapability(pszCap);
312 : }
313 :
314 19 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
315 : bool bForce) override
316 : {
317 19 : return m_srcLayer.GetExtent(iGeomField, psExtent, bForce);
318 : }
319 :
320 1 : OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent,
321 : bool bForce) override
322 : {
323 1 : return m_srcLayer.GetExtent3D(iGeomField, psExtent, bForce);
324 : }
325 :
326 : void TranslateFeature(
327 : std::unique_ptr<OGRFeature> poSrcFeature,
328 : std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override;
329 : };
330 :
331 : /************************************************************************/
332 : /* GDALVectorNonStreamingAlgorithmLayer */
333 : /************************************************************************/
334 :
335 : /**
336 : * This class represents a layer for algorithms that process vector data
337 : * in a non-streaming manner.
338 : *
339 : * Implementations must override the following methods:
340 : * - Process(), which is called when the first feature is read
341 : * - GetNextProcessedFeature() method which provides features in sequential order
342 : */
343 71 : class GDALVectorNonStreamingAlgorithmLayer
344 : : public OGRLayer,
345 : public OGRGetNextFeatureThroughRaw<GDALVectorNonStreamingAlgorithmLayer>
346 : {
347 : public:
348 : GDALVectorNonStreamingAlgorithmLayer(OGRLayer &srcLayer,
349 : int geomFieldIndex);
350 :
351 : ~GDALVectorNonStreamingAlgorithmLayer() override;
352 :
353 5 : const char *GetDescription() const override
354 : {
355 5 : return GetName();
356 : }
357 :
358 : virtual bool Process(GDALProgressFunc pfnProgress, void *pProgressData) = 0;
359 :
360 : virtual std::unique_ptr<OGRFeature> GetNextProcessedFeature() = 0;
361 :
362 : OGRFeature *GetNextRawFeature();
363 :
364 2141 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorNonStreamingAlgorithmLayer)
365 :
366 : protected:
367 : OGRLayer &m_srcLayer;
368 : int m_geomFieldIndex{0};
369 :
370 : private:
371 : CPL_DISALLOW_COPY_ASSIGN(GDALVectorNonStreamingAlgorithmLayer)
372 : };
373 :
374 : /************************************************************************/
375 : /* GDALVectorNonStreamingAlgorithmDataset */
376 : /************************************************************************/
377 :
378 : /**
379 : * Dataset used to read all input features into memory and perform some
380 : * processing.
381 : */
382 158 : class GDALVectorNonStreamingAlgorithmDataset /* non final */
383 : : public GDALVectorDecoratedDataset
384 : {
385 : public:
386 : explicit GDALVectorNonStreamingAlgorithmDataset(GDALDataset &oSrcDS);
387 : ~GDALVectorNonStreamingAlgorithmDataset() override;
388 :
389 : /** Add a layer to the dataset and perform the associated processing. */
390 : bool AddProcessedLayer(
391 : std::unique_ptr<GDALVectorNonStreamingAlgorithmLayer> srcLayer,
392 : GDALProgressFunc progressFunc, void *progressData);
393 :
394 : void AddPassThroughLayer(OGRLayer &oLayer);
395 :
396 : int GetLayerCount() const final override;
397 : OGRLayer *GetLayer(int idx) const final override;
398 : int TestCapability(const char *pszCap) const override;
399 :
400 : private:
401 : std::vector<std::unique_ptr<OGRLayer>> m_owned_layers{};
402 : std::vector<OGRLayer *> m_layers{};
403 : };
404 :
405 : /************************************************************************/
406 : /* GDALVectorPipelineOutputDataset */
407 : /************************************************************************/
408 :
409 : /** Class used by vector pipeline steps to create an output on-the-fly
410 : * dataset where they can store on-the-fly layers.
411 : */
412 : class GDALVectorPipelineOutputDataset /* non final */
413 : : public GDALVectorDecoratedDataset
414 : {
415 : std::map<OGRLayer *, OGRLayerWithTranslateFeature *>
416 : m_mapSrcLayerToNewLayer{};
417 : std::vector<std::unique_ptr<OGRLayerWithTranslateFeature>>
418 : m_layersToDestroy{};
419 : std::vector<OGRLayerWithTranslateFeature *> m_layers{};
420 :
421 : OGRLayerWithTranslateFeature *m_belongingLayer = nullptr;
422 : std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
423 : size_t m_idxInPendingFeatures = 0;
424 :
425 : CPL_DISALLOW_COPY_ASSIGN(GDALVectorPipelineOutputDataset)
426 :
427 : public:
428 : explicit GDALVectorPipelineOutputDataset(GDALDataset &oSrcDS);
429 :
430 : void AddLayer(OGRLayer &oSrcLayer,
431 : std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer);
432 :
433 : int GetLayerCount() const override;
434 :
435 : OGRLayer *GetLayer(int idx) const override;
436 :
437 : int TestCapability(const char *pszCap) const override;
438 :
439 : void ResetReading() override;
440 :
441 : OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer,
442 : double *pdfProgressPct,
443 : GDALProgressFunc pfnProgress,
444 : void *pProgressData) override;
445 : };
446 :
447 : //! @endcond
448 :
449 : #endif
|