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 1051 : class GDALVectorPipelineStepAlgorithm /* non final */ 32 : : public GDALPipelineStepAlgorithm 33 : { 34 : public: 35 : ~GDALVectorPipelineStepAlgorithm() override; 36 : 37 : protected: 38 : GDALVectorPipelineStepAlgorithm(const std::string &name, 39 : const std::string &description, 40 : const std::string &helpURL, 41 : bool standaloneStep); 42 : 43 : GDALVectorPipelineStepAlgorithm(const std::string &name, 44 : const std::string &description, 45 : const std::string &helpURL, 46 : const ConstructorOptions &options); 47 : 48 : friend class GDALVectorPipelineAlgorithm; 49 : friend class GDALAbstractPipelineAlgorithm<GDALVectorPipelineStepAlgorithm>; 50 : friend class GDALVectorConcatAlgorithm; 51 : 52 135 : int GetInputType() const override 53 : { 54 135 : return GDAL_OF_VECTOR; 55 : } 56 : 57 141 : int GetOutputType() const override 58 : { 59 141 : return GDAL_OF_VECTOR; 60 : } 61 : }; 62 : 63 : /************************************************************************/ 64 : /* GDALVectorPipelineAlgorithm */ 65 : /************************************************************************/ 66 : 67 : // This is an easter egg to pay tribute to PROJ pipeline syntax 68 : // We accept "gdal vector +gdal=pipeline +step +gdal=read +input=poly.gpkg +step +gdal=reproject +dst-crs=EPSG:32632 +step +gdal=write +output=out.gpkg +overwrite" 69 : // as an alternative to (recommended): 70 : // "gdal vector pipeline ! read poly.gpkg ! reproject--dst-crs=EPSG:32632 ! write out.gpkg --overwrite" 71 : #define GDAL_PIPELINE_PROJ_NOSTALGIA 72 : 73 : class GDALVectorPipelineAlgorithm final 74 : : public GDALAbstractPipelineAlgorithm<GDALVectorPipelineStepAlgorithm> 75 : { 76 : public: 77 : static constexpr const char *NAME = "pipeline"; 78 : static constexpr const char *DESCRIPTION = "Process a vector dataset."; 79 : static constexpr const char *HELP_URL = 80 : "/programs/gdal_vector_pipeline.html"; 81 : 82 526 : static std::vector<std::string> GetAliasesStatic() 83 : { 84 : return { 85 : #ifdef GDAL_PIPELINE_PROJ_NOSTALGIA 86 : GDALAlgorithmRegistry::HIDDEN_ALIAS_SEPARATOR, 87 : "+pipeline", 88 : "+gdal=pipeline", 89 : #endif 90 2104 : }; 91 : } 92 : 93 : GDALVectorPipelineAlgorithm(); 94 : 95 : bool 96 : ParseCommandLineArguments(const std::vector<std::string> &args) override; 97 : 98 : std::string GetUsageForCLI(bool shortUsage, 99 : const UsageOptions &usageOptions) const override; 100 : 101 : static void RegisterAlgorithms(GDALAlgorithmRegistry ®istry, 102 : bool forMixedPipeline); 103 : }; 104 : 105 : /************************************************************************/ 106 : /* GDALVectorPipelineOutputLayer */ 107 : /************************************************************************/ 108 : 109 : /** Class that implements GetNextFeature() by forwarding to 110 : * OGRLayerWithTranslateFeature::TranslateFeature() implementation, which 111 : * might return several features. 112 : */ 113 106 : class GDALVectorPipelineOutputLayer /* non final */ 114 : : public OGRLayerWithTranslateFeature, 115 : public OGRGetNextFeatureThroughRaw<GDALVectorPipelineOutputLayer> 116 : { 117 : protected: 118 : explicit GDALVectorPipelineOutputLayer(OGRLayer &oSrcLayer); 119 : ~GDALVectorPipelineOutputLayer(); 120 : 121 1426 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorPipelineOutputLayer) 122 : 123 : OGRLayer &m_srcLayer; 124 : 125 : public: 126 : void ResetReading() override; 127 : OGRFeature *GetNextRawFeature(); 128 : 129 : private: 130 : std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{}; 131 : size_t m_idxInPendingFeatures = 0; 132 : }; 133 : 134 : /************************************************************************/ 135 : /* GDALVectorPipelinePassthroughLayer */ 136 : /************************************************************************/ 137 : 138 : /** Class that forwards GetNextFeature() calls to the source layer and 139 : * can be added to GDALVectorPipelineOutputDataset::AddLayer() 140 : */ 141 : class GDALVectorPipelinePassthroughLayer /* non final */ 142 : : public GDALVectorPipelineOutputLayer 143 : { 144 : public: 145 9 : explicit GDALVectorPipelinePassthroughLayer(OGRLayer &oSrcLayer) 146 9 : : GDALVectorPipelineOutputLayer(oSrcLayer) 147 : { 148 9 : } 149 : 150 : OGRFeatureDefn *GetLayerDefn() override; 151 : 152 4 : int TestCapability(const char *pszCap) override 153 : { 154 4 : return m_srcLayer.TestCapability(pszCap); 155 : } 156 : 157 25 : void TranslateFeature( 158 : std::unique_ptr<OGRFeature> poSrcFeature, 159 : std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override 160 : { 161 25 : apoOutFeatures.push_back(std::move(poSrcFeature)); 162 25 : } 163 : }; 164 : 165 : /************************************************************************/ 166 : /* GDALVectorNonStreamingAlgorithmDataset */ 167 : /************************************************************************/ 168 : 169 : class MEMDataset; 170 : 171 : /** 172 : * Dataset used to read all input features into memory and perform some 173 : * processing. 174 : */ 175 8 : class GDALVectorNonStreamingAlgorithmDataset /* non final */ 176 : : public GDALDataset 177 : { 178 : public: 179 : GDALVectorNonStreamingAlgorithmDataset(); 180 : ~GDALVectorNonStreamingAlgorithmDataset(); 181 : 182 : virtual bool Process(OGRLayer &srcLayer, OGRLayer &dstLayer) = 0; 183 : 184 : bool AddProcessedLayer(OGRLayer &srcLayer); 185 : void AddPassThroughLayer(OGRLayer &oLayer); 186 : int GetLayerCount() final override; 187 : OGRLayer *GetLayer(int idx) final override; 188 : int TestCapability(const char *pszCap) override; 189 : 190 : private: 191 : std::vector<std::unique_ptr<OGRLayer>> m_passthrough_layers{}; 192 : std::vector<OGRLayer *> m_layers{}; 193 : std::unique_ptr<MEMDataset> m_ds{}; 194 : }; 195 : 196 : /************************************************************************/ 197 : /* GDALVectorPipelineOutputDataset */ 198 : /************************************************************************/ 199 : 200 : /** Class used by vector pipeline steps to create an output on-the-fly 201 : * dataset where they can store on-the-fly layers. 202 : */ 203 198 : class GDALVectorPipelineOutputDataset final : public GDALDataset 204 : { 205 : GDALDataset &m_srcDS; 206 : std::map<OGRLayer *, OGRLayerWithTranslateFeature *> 207 : m_mapSrcLayerToNewLayer{}; 208 : std::vector<std::unique_ptr<OGRLayerWithTranslateFeature>> 209 : m_layersToDestroy{}; 210 : std::vector<OGRLayerWithTranslateFeature *> m_layers{}; 211 : 212 : OGRLayerWithTranslateFeature *m_belongingLayer = nullptr; 213 : std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{}; 214 : size_t m_idxInPendingFeatures = 0; 215 : 216 : CPL_DISALLOW_COPY_ASSIGN(GDALVectorPipelineOutputDataset) 217 : 218 : public: 219 : explicit GDALVectorPipelineOutputDataset(GDALDataset &oSrcDS); 220 : ~GDALVectorPipelineOutputDataset(); 221 : 222 : void AddLayer(OGRLayer &oSrcLayer, 223 : std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer); 224 : 225 : int GetLayerCount() override; 226 : 227 : OGRLayer *GetLayer(int idx) override; 228 : 229 : int TestCapability(const char *pszCap) override; 230 : 231 : void ResetReading() override; 232 : 233 : OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer, 234 : double *pdfProgressPct, 235 : GDALProgressFunc pfnProgress, 236 : void *pProgressData) override; 237 : }; 238 : 239 : //! @endcond 240 : 241 : #endif