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 GDALVectorPipelineStepAlgorithm /* non final */ : public GDALAlgorithm 32 : { 33 : protected: 34 : GDALVectorPipelineStepAlgorithm(const std::string &name, 35 : const std::string &description, 36 : const std::string &helpURL, 37 : bool standaloneStep); 38 : 39 : friend class GDALVectorPipelineAlgorithm; 40 : friend class GDALAbstractPipelineAlgorithm<GDALVectorPipelineStepAlgorithm>; 41 : 42 : virtual bool RunStep(GDALProgressFunc pfnProgress, void *pProgressData) = 0; 43 : 44 : void AddInputArgs(bool hiddenForCLI); 45 : void AddOutputArgs(bool hiddenForCLI, bool shortNameOutputLayerAllowed); 46 : 47 : bool m_standaloneStep = false; 48 : 49 : // Input arguments 50 : GDALArgDatasetValue m_inputDataset{}; 51 : std::vector<std::string> m_openOptions{}; 52 : std::vector<std::string> m_inputFormats{}; 53 : std::vector<std::string> m_inputLayerNames{}; 54 : 55 : // Output arguments 56 : GDALArgDatasetValue m_outputDataset{}; 57 : std::string m_format{}; 58 : std::vector<std::string> m_creationOptions{}; 59 : std::vector<std::string> m_layerCreationOptions{}; 60 : bool m_overwrite = false; 61 : bool m_update = false; 62 : bool m_overwriteLayer = false; 63 : bool m_appendLayer = false; 64 : std::string m_outputLayerName{}; 65 : 66 : private: 67 : bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) override; 68 : }; 69 : 70 : /************************************************************************/ 71 : /* GDALVectorPipelineAlgorithm */ 72 : /************************************************************************/ 73 : 74 : // This is an easter egg to pay tribute to PROJ pipeline syntax 75 : // 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" 76 : // as an alternative to (recommended): 77 : // "gdal vector pipeline ! read poly.gpkg ! reproject--dst-crs=EPSG:32632 ! write out.gpkg --overwrite" 78 : #define GDAL_PIPELINE_PROJ_NOSTALGIA 79 : 80 : class GDALVectorPipelineAlgorithm final 81 : : public GDALAbstractPipelineAlgorithm<GDALVectorPipelineStepAlgorithm> 82 : { 83 : public: 84 : static constexpr const char *NAME = "pipeline"; 85 : static constexpr const char *DESCRIPTION = "Process a vector dataset."; 86 : static constexpr const char *HELP_URL = 87 : "/programs/gdal_vector_pipeline.html"; 88 : 89 139 : static std::vector<std::string> GetAliases() 90 : { 91 : return { 92 : #ifdef GDAL_PIPELINE_PROJ_NOSTALGIA 93 : GDALAlgorithmRegistry::HIDDEN_ALIAS_SEPARATOR, 94 : "+pipeline", 95 : "+gdal=pipeline", 96 : #endif 97 556 : }; 98 : } 99 : 100 : GDALVectorPipelineAlgorithm(); 101 : 102 : bool 103 : ParseCommandLineArguments(const std::vector<std::string> &args) override; 104 : 105 : std::string GetUsageForCLI(bool shortUsage, 106 : const UsageOptions &usageOptions) const override; 107 : 108 : protected: 109 50 : GDALArgDatasetValue &GetOutputDataset() override 110 : { 111 50 : return m_outputDataset; 112 : } 113 : }; 114 : 115 : /************************************************************************/ 116 : /* GDALVectorPipelineOutputLayer */ 117 : /************************************************************************/ 118 : 119 : /** Class that implements GetNextFeature() by forwarding to 120 : * OGRLayerWithTranslateFeature::TranslateFeature() implementation, which 121 : * might return several features. 122 : */ 123 : class GDALVectorPipelineOutputLayer /* non final */ 124 : : public OGRLayerWithTranslateFeature, 125 : public OGRGetNextFeatureThroughRaw<GDALVectorPipelineOutputLayer> 126 : { 127 : protected: 128 : explicit GDALVectorPipelineOutputLayer(OGRLayer &oSrcLayer); 129 : 130 90 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorPipelineOutputLayer) 131 : 132 : OGRLayer &m_srcLayer; 133 : 134 : public: 135 : void ResetReading() override; 136 : OGRFeature *GetNextRawFeature(); 137 : 138 : private: 139 : std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{}; 140 : size_t m_idxInPendingFeatures = 0; 141 : }; 142 : 143 : /************************************************************************/ 144 : /* GDALVectorPipelineOutputDataset */ 145 : /************************************************************************/ 146 : 147 : /** Class used by vector pipeline steps to create an output on-the-fly 148 : * dataset where they can store on-the-fly layers. 149 : */ 150 : class GDALVectorPipelineOutputDataset final : public GDALDataset 151 : { 152 : GDALDataset &m_srcDS; 153 : std::map<OGRLayer *, OGRLayerWithTranslateFeature *> 154 : m_mapSrcLayerToNewLayer{}; 155 : std::vector<std::unique_ptr<OGRLayerWithTranslateFeature>> 156 : m_layersToDestroy{}; 157 : std::vector<OGRLayerWithTranslateFeature *> m_layers{}; 158 : 159 : OGRLayerWithTranslateFeature *m_belongingLayer = nullptr; 160 : std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{}; 161 : size_t m_idxInPendingFeatures = 0; 162 : 163 : CPL_DISALLOW_COPY_ASSIGN(GDALVectorPipelineOutputDataset) 164 : 165 : public: 166 : explicit GDALVectorPipelineOutputDataset(GDALDataset &oSrcDS); 167 : 168 : void AddLayer(OGRLayer &oSrcLayer, 169 : std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer); 170 : 171 : int GetLayerCount() override; 172 : 173 : OGRLayer *GetLayer(int idx) override; 174 : 175 : int TestCapability(const char *pszCap) override; 176 : 177 : void ResetReading() override; 178 : 179 : OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer, 180 : double *pdfProgressPct, 181 : GDALProgressFunc pfnProgress, 182 : void *pProgressData) override; 183 : }; 184 : 185 : //! @endcond 186 : 187 : #endif