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