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 GDALALG_VECTOR_PIPELINE_INCLUDED 14 : #define GDALALG_VECTOR_PIPELINE_INCLUDED 15 : 16 : #include "gdalalgorithm.h" 17 : #include "gdalalg_abstract_pipeline.h" 18 : 19 : #include "ogrsf_frmts.h" 20 : #include "ogrlayerwithtranslatefeature.h" 21 : 22 : #include <map> 23 : #include <vector> 24 : 25 : //! @cond Doxygen_Suppress 26 : 27 : /************************************************************************/ 28 : /* GDALVectorPipelineStepAlgorithm */ 29 : /************************************************************************/ 30 : 31 : class GDALRasterAlgorithmStepRegistry; 32 : 33 2224 : class GDALVectorPipelineStepAlgorithm /* non final */ 34 : : public GDALPipelineStepAlgorithm 35 : { 36 : public: 37 : ~GDALVectorPipelineStepAlgorithm() override; 38 : 39 : protected: 40 : GDALVectorPipelineStepAlgorithm(const std::string &name, 41 : const std::string &description, 42 : const std::string &helpURL, 43 : bool standaloneStep); 44 : 45 : GDALVectorPipelineStepAlgorithm(const std::string &name, 46 : const std::string &description, 47 : const std::string &helpURL, 48 : const ConstructorOptions &options); 49 : 50 : friend class GDALVectorPipelineAlgorithm; 51 : friend class GDALVectorConcatAlgorithm; 52 : 53 279 : int GetInputType() const override 54 : { 55 279 : return GDAL_OF_VECTOR; 56 : } 57 : 58 263 : int GetOutputType() const override 59 : { 60 263 : return GDAL_OF_VECTOR; 61 : } 62 : }; 63 : 64 : /************************************************************************/ 65 : /* GDALVectorAlgorithmStepRegistry */ 66 : /************************************************************************/ 67 : 68 274 : class GDALVectorAlgorithmStepRegistry : public virtual GDALAlgorithmRegistry 69 : { 70 : public: 71 274 : GDALVectorAlgorithmStepRegistry() = default; 72 : ~GDALVectorAlgorithmStepRegistry() override; 73 : 74 : /** Register the algorithm of type MyAlgorithm. 75 : */ 76 : template <class MyAlgorithm> 77 6850 : bool Register(const std::string &name = std::string()) 78 : { 79 : static_assert( 80 : std::is_base_of_v<GDALVectorPipelineStepAlgorithm, MyAlgorithm>, 81 : "Algorithm is not a GDALVectorPipelineStepAlgorithm"); 82 : 83 13700 : AlgInfo info; 84 6850 : info.m_name = name.empty() ? MyAlgorithm::NAME : name; 85 6850 : info.m_aliases = MyAlgorithm::GetAliasesStatic(); 86 8219 : info.m_creationFunc = []() -> std::unique_ptr<GDALAlgorithm> 87 1369 : { return std::make_unique<MyAlgorithm>(); }; 88 13700 : return GDALAlgorithmRegistry::Register(info); 89 : } 90 : }; 91 : 92 : /************************************************************************/ 93 : /* GDALVectorPipelineAlgorithm */ 94 : /************************************************************************/ 95 : 96 : class GDALVectorPipelineAlgorithm final : public GDALAbstractPipelineAlgorithm 97 : { 98 : public: 99 : static constexpr const char *NAME = "pipeline"; 100 : static constexpr const char *DESCRIPTION = 101 : "Process a vector dataset applying several steps."; 102 : static constexpr const char *HELP_URL = 103 : "/programs/gdal_vector_pipeline.html"; 104 : 105 649 : static std::vector<std::string> GetAliasesStatic() 106 : { 107 : return { 108 : #ifdef GDAL_PIPELINE_PROJ_NOSTALGIA 109 : GDALAlgorithmRegistry::HIDDEN_ALIAS_SEPARATOR, 110 : "+pipeline", 111 : "+gdal=pipeline", 112 : #endif 113 2596 : }; 114 : } 115 : 116 : GDALVectorPipelineAlgorithm(); 117 : 118 : std::string GetUsageForCLI(bool shortUsage, 119 : const UsageOptions &usageOptions) const override; 120 : 121 : static void RegisterAlgorithms(GDALVectorAlgorithmStepRegistry ®istry, 122 : bool forMixedPipeline); 123 : 124 95 : int GetInputType() const override 125 : { 126 95 : return GDAL_OF_VECTOR; 127 : } 128 : 129 0 : int GetOutputType() const override 130 : { 131 0 : return GDAL_OF_VECTOR; 132 : } 133 : 134 : protected: 135 : GDALVectorAlgorithmStepRegistry m_stepRegistry{}; 136 : 137 146 : GDALAlgorithmRegistry &GetStepRegistry() override 138 : { 139 146 : return m_stepRegistry; 140 : } 141 : 142 712 : const GDALAlgorithmRegistry &GetStepRegistry() const override 143 : { 144 712 : return m_stepRegistry; 145 : } 146 : 147 : private: 148 : std::unique_ptr<GDALAbstractPipelineAlgorithm> 149 0 : CreateNestedPipeline() const override 150 : { 151 0 : return std::make_unique<GDALVectorPipelineAlgorithm>(); 152 : } 153 : }; 154 : 155 : /************************************************************************/ 156 : /* GDALVectorPipelineOutputLayer */ 157 : /************************************************************************/ 158 : 159 : /** Class that implements GetNextFeature() by forwarding to 160 : * OGRLayerWithTranslateFeature::TranslateFeature() implementation, which 161 : * might return several features. 162 : */ 163 129 : class GDALVectorPipelineOutputLayer /* non final */ 164 : : public OGRLayerWithTranslateFeature, 165 : public OGRGetNextFeatureThroughRaw<GDALVectorPipelineOutputLayer> 166 : { 167 : protected: 168 : explicit GDALVectorPipelineOutputLayer(OGRLayer &oSrcLayer); 169 : ~GDALVectorPipelineOutputLayer() override; 170 : 171 1553 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorPipelineOutputLayer) 172 : 173 : OGRLayer &m_srcLayer; 174 : 175 : public: 176 : void ResetReading() override; 177 : OGRFeature *GetNextRawFeature(); 178 : 179 : private: 180 : std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{}; 181 : size_t m_idxInPendingFeatures = 0; 182 : }; 183 : 184 : /************************************************************************/ 185 : /* GDALVectorPipelinePassthroughLayer */ 186 : /************************************************************************/ 187 : 188 : /** Class that forwards GetNextFeature() calls to the source layer and 189 : * can be added to GDALVectorPipelineOutputDataset::AddLayer() 190 : */ 191 : class GDALVectorPipelinePassthroughLayer /* non final */ 192 : : public GDALVectorPipelineOutputLayer 193 : { 194 : public: 195 12 : explicit GDALVectorPipelinePassthroughLayer(OGRLayer &oSrcLayer) 196 12 : : GDALVectorPipelineOutputLayer(oSrcLayer) 197 : { 198 12 : } 199 : 200 : const OGRFeatureDefn *GetLayerDefn() const override; 201 : 202 4 : int TestCapability(const char *pszCap) const override 203 : { 204 4 : return m_srcLayer.TestCapability(pszCap); 205 : } 206 : 207 28 : void TranslateFeature( 208 : std::unique_ptr<OGRFeature> poSrcFeature, 209 : std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override 210 : { 211 28 : apoOutFeatures.push_back(std::move(poSrcFeature)); 212 28 : } 213 : }; 214 : 215 : /************************************************************************/ 216 : /* GDALVectorNonStreamingAlgorithmDataset */ 217 : /************************************************************************/ 218 : 219 : class MEMDataset; 220 : 221 : /** 222 : * Dataset used to read all input features into memory and perform some 223 : * processing. 224 : */ 225 30 : class GDALVectorNonStreamingAlgorithmDataset /* non final */ 226 : : public GDALDataset 227 : { 228 : public: 229 : GDALVectorNonStreamingAlgorithmDataset(); 230 : ~GDALVectorNonStreamingAlgorithmDataset() override; 231 : 232 : virtual bool Process(OGRLayer &srcLayer, OGRLayer &dstLayer) = 0; 233 : 234 : bool AddProcessedLayer(OGRLayer &srcLayer); 235 : bool AddProcessedLayer(OGRLayer &srcLayer, OGRFeatureDefn &dstDefn); 236 : void AddPassThroughLayer(OGRLayer &oLayer); 237 : int GetLayerCount() const final override; 238 : OGRLayer *GetLayer(int idx) const final override; 239 : int TestCapability(const char *pszCap) const override; 240 : 241 : private: 242 : std::vector<std::unique_ptr<OGRLayer>> m_passthrough_layers{}; 243 : std::vector<OGRLayer *> m_layers{}; 244 : std::unique_ptr<MEMDataset> m_ds{}; 245 : }; 246 : 247 : /************************************************************************/ 248 : /* GDALVectorPipelineOutputDataset */ 249 : /************************************************************************/ 250 : 251 : /** Class used by vector pipeline steps to create an output on-the-fly 252 : * dataset where they can store on-the-fly layers. 253 : */ 254 : class GDALVectorPipelineOutputDataset final : public GDALDataset 255 : { 256 : GDALDataset &m_srcDS; 257 : std::map<OGRLayer *, OGRLayerWithTranslateFeature *> 258 : m_mapSrcLayerToNewLayer{}; 259 : std::vector<std::unique_ptr<OGRLayerWithTranslateFeature>> 260 : m_layersToDestroy{}; 261 : std::vector<OGRLayerWithTranslateFeature *> m_layers{}; 262 : 263 : OGRLayerWithTranslateFeature *m_belongingLayer = nullptr; 264 : std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{}; 265 : size_t m_idxInPendingFeatures = 0; 266 : 267 : CPL_DISALLOW_COPY_ASSIGN(GDALVectorPipelineOutputDataset) 268 : 269 : public: 270 : explicit GDALVectorPipelineOutputDataset(GDALDataset &oSrcDS); 271 : 272 : void AddLayer(OGRLayer &oSrcLayer, 273 : std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer); 274 : 275 : int GetLayerCount() const override; 276 : 277 : OGRLayer *GetLayer(int idx) const override; 278 : 279 : int TestCapability(const char *pszCap) const override; 280 : 281 : void ResetReading() override; 282 : 283 : OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer, 284 : double *pdfProgressPct, 285 : GDALProgressFunc pfnProgress, 286 : void *pProgressData) override; 287 : }; 288 : 289 : //! @endcond 290 : 291 : #endif