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 2129 : 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 316 : int GetInputType() const override 54 : { 55 316 : return GDAL_OF_VECTOR; 56 : } 57 : 58 303 : int GetOutputType() const override 59 : { 60 303 : return GDAL_OF_VECTOR; 61 : } 62 : }; 63 : 64 : /************************************************************************/ 65 : /* GDALVectorAlgorithmStepRegistry */ 66 : /************************************************************************/ 67 : 68 281 : class GDALVectorAlgorithmStepRegistry : public virtual GDALAlgorithmRegistry 69 : { 70 : public: 71 281 : GDALVectorAlgorithmStepRegistry() = default; 72 : ~GDALVectorAlgorithmStepRegistry() override; 73 : 74 : /** Register the algorithm of type MyAlgorithm. 75 : */ 76 : template <class MyAlgorithm> 77 7306 : 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 14612 : AlgInfo info; 84 7306 : info.m_name = name.empty() ? MyAlgorithm::NAME : name; 85 7306 : info.m_aliases = MyAlgorithm::GetAliasesStatic(); 86 8477 : info.m_creationFunc = []() -> std::unique_ptr<GDALAlgorithm> 87 1171 : { return std::make_unique<MyAlgorithm>(); }; 88 14612 : 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 687 : 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 2748 : }; 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 94 : int GetInputType() const override 125 : { 126 94 : 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 152 : GDALAlgorithmRegistry &GetStepRegistry() override 138 : { 139 152 : return m_stepRegistry; 140 : } 141 : 142 618 : const GDALAlgorithmRegistry &GetStepRegistry() const override 143 : { 144 618 : return m_stepRegistry; 145 : } 146 : 147 : private: 148 : std::unique_ptr<GDALAbstractPipelineAlgorithm> 149 0 : CreateNestedPipeline() const override 150 : { 151 0 : auto pipeline = std::make_unique<GDALVectorPipelineAlgorithm>(); 152 0 : pipeline->m_bInnerPipeline = true; 153 0 : return pipeline; 154 : } 155 : }; 156 : 157 : /************************************************************************/ 158 : /* GDALVectorPipelineOutputLayer */ 159 : /************************************************************************/ 160 : 161 : /** Class that implements GetNextFeature() by forwarding to 162 : * OGRLayerWithTranslateFeature::TranslateFeature() implementation, which 163 : * might return several features. 164 : */ 165 167 : class GDALVectorPipelineOutputLayer /* non final */ 166 : : public OGRLayerWithTranslateFeature, 167 : public OGRGetNextFeatureThroughRaw<GDALVectorPipelineOutputLayer> 168 : { 169 : protected: 170 : explicit GDALVectorPipelineOutputLayer(OGRLayer &oSrcLayer); 171 : ~GDALVectorPipelineOutputLayer() override; 172 : 173 1622 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorPipelineOutputLayer) 174 : 175 : OGRLayer &m_srcLayer; 176 : 177 : public: 178 : void ResetReading() override; 179 : OGRFeature *GetNextRawFeature(); 180 : 181 : private: 182 : std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{}; 183 : size_t m_idxInPendingFeatures = 0; 184 : }; 185 : 186 : /************************************************************************/ 187 : /* GDALVectorPipelinePassthroughLayer */ 188 : /************************************************************************/ 189 : 190 : /** Class that forwards GetNextFeature() calls to the source layer and 191 : * can be added to GDALVectorPipelineOutputDataset::AddLayer() 192 : */ 193 : class GDALVectorPipelinePassthroughLayer /* non final */ 194 : : public GDALVectorPipelineOutputLayer 195 : { 196 : public: 197 12 : explicit GDALVectorPipelinePassthroughLayer(OGRLayer &oSrcLayer) 198 12 : : GDALVectorPipelineOutputLayer(oSrcLayer) 199 : { 200 12 : } 201 : 202 : const OGRFeatureDefn *GetLayerDefn() const override; 203 : 204 4 : int TestCapability(const char *pszCap) const override 205 : { 206 4 : return m_srcLayer.TestCapability(pszCap); 207 : } 208 : 209 28 : void TranslateFeature( 210 : std::unique_ptr<OGRFeature> poSrcFeature, 211 : std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override 212 : { 213 28 : apoOutFeatures.push_back(std::move(poSrcFeature)); 214 28 : } 215 : }; 216 : 217 : /************************************************************************/ 218 : /* GDALVectorNonStreamingAlgorithmDataset */ 219 : /************************************************************************/ 220 : 221 : class MEMDataset; 222 : 223 : /** 224 : * Dataset used to read all input features into memory and perform some 225 : * processing. 226 : */ 227 30 : class GDALVectorNonStreamingAlgorithmDataset /* non final */ 228 : : public GDALDataset 229 : { 230 : public: 231 : GDALVectorNonStreamingAlgorithmDataset(); 232 : ~GDALVectorNonStreamingAlgorithmDataset() override; 233 : 234 : virtual bool Process(OGRLayer &srcLayer, OGRLayer &dstLayer) = 0; 235 : 236 : bool AddProcessedLayer(OGRLayer &srcLayer); 237 : bool AddProcessedLayer(OGRLayer &srcLayer, OGRFeatureDefn &dstDefn); 238 : void AddPassThroughLayer(OGRLayer &oLayer); 239 : int GetLayerCount() const final override; 240 : OGRLayer *GetLayer(int idx) const final override; 241 : int TestCapability(const char *pszCap) const override; 242 : 243 : private: 244 : std::vector<std::unique_ptr<OGRLayer>> m_passthrough_layers{}; 245 : std::vector<OGRLayer *> m_layers{}; 246 : std::unique_ptr<MEMDataset> m_ds{}; 247 : }; 248 : 249 : /************************************************************************/ 250 : /* GDALVectorPipelineOutputDataset */ 251 : /************************************************************************/ 252 : 253 : /** Class used by vector pipeline steps to create an output on-the-fly 254 : * dataset where they can store on-the-fly layers. 255 : */ 256 : class GDALVectorPipelineOutputDataset final : public GDALDataset 257 : { 258 : GDALDataset &m_srcDS; 259 : std::map<OGRLayer *, OGRLayerWithTranslateFeature *> 260 : m_mapSrcLayerToNewLayer{}; 261 : std::vector<std::unique_ptr<OGRLayerWithTranslateFeature>> 262 : m_layersToDestroy{}; 263 : std::vector<OGRLayerWithTranslateFeature *> m_layers{}; 264 : 265 : OGRLayerWithTranslateFeature *m_belongingLayer = nullptr; 266 : std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{}; 267 : size_t m_idxInPendingFeatures = 0; 268 : 269 : CPL_DISALLOW_COPY_ASSIGN(GDALVectorPipelineOutputDataset) 270 : 271 : public: 272 : explicit GDALVectorPipelineOutputDataset(GDALDataset &oSrcDS); 273 : 274 : void AddLayer(OGRLayer &oSrcLayer, 275 : std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer); 276 : 277 : int GetLayerCount() const override; 278 : 279 : OGRLayer *GetLayer(int idx) const override; 280 : 281 : int TestCapability(const char *pszCap) const override; 282 : 283 : void ResetReading() override; 284 : 285 : OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer, 286 : double *pdfProgressPct, 287 : GDALProgressFunc pfnProgress, 288 : void *pProgressData) override; 289 : }; 290 : 291 : //! @endcond 292 : 293 : #endif