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