Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: "geom" step of "vector pipeline", or "gdal vector geom" standalone 5 : * Author: Even Rouault <even dot rouault at spatialys.com> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #ifndef GDALALG_VECTOR_GEOM_INCLUDED 14 : #define GDALALG_VECTOR_GEOM_INCLUDED 15 : 16 : #include "gdalalg_vector_pipeline.h" 17 : 18 : //! @cond Doxygen_Suppress 19 : 20 : /************************************************************************/ 21 : /* GDALVectorGeomAlgorithm */ 22 : /************************************************************************/ 23 : 24 : class GDALVectorGeomAlgorithm /* non final */ 25 : : public GDALVectorPipelineStepAlgorithm 26 : { 27 : public: 28 : static constexpr const char *NAME = "geom"; 29 : static constexpr const char *DESCRIPTION = 30 : "Geometry operations on a vector dataset."; 31 : static constexpr const char *HELP_URL = "/programs/gdal_vector_geom.html"; 32 : 33 340 : static std::vector<std::string> GetAliases() 34 : { 35 340 : return {}; 36 : } 37 : 38 : explicit GDALVectorGeomAlgorithm(bool standaloneStep = false); 39 : 40 : private: 41 : bool RunStep(GDALProgressFunc pfnProgress, void *pProgressData) override; 42 : 43 : /** Register the sub-algorithm of type MyAlgorithm. 44 : */ 45 518 : template <class MyAlgorithm> bool RegisterSubAlgorithm(bool standalone) 46 : { 47 1036 : GDALAlgorithmRegistry::AlgInfo info; 48 518 : info.m_name = MyAlgorithm::NAME; 49 518 : info.m_aliases = MyAlgorithm::GetAliases(); 50 617 : info.m_creationFunc = [standalone]() -> std::unique_ptr<GDALAlgorithm> 51 99 : { return std::make_unique<MyAlgorithm>(standalone); }; 52 1036 : return GDALAlgorithm::RegisterSubAlgorithm(info); 53 : } 54 : }; 55 : 56 : /************************************************************************/ 57 : /* GDALVectorGeomAlgorithmStandalone */ 58 : /************************************************************************/ 59 : 60 : class GDALVectorGeomAlgorithmStandalone final : public GDALVectorGeomAlgorithm 61 : { 62 : public: 63 64 : GDALVectorGeomAlgorithmStandalone() 64 64 : : GDALVectorGeomAlgorithm(/* standaloneStep = */ true) 65 : { 66 64 : } 67 : }; 68 : 69 : /************************************************************************/ 70 : /* GDALVectorGeomAbstractAlgorithm */ 71 : /************************************************************************/ 72 : 73 : class GDALVectorGeomAbstractAlgorithm /* non final */ 74 : : public GDALVectorPipelineStepAlgorithm 75 : { 76 : protected: 77 : struct OptionsBase 78 : { 79 : std::string m_activeLayer{}; 80 : std::string m_geomField{}; 81 : }; 82 : 83 : virtual std::unique_ptr<OGRLayerWithTranslateFeature> 84 : CreateAlgLayer(OGRLayer &srcLayer) = 0; 85 : 86 : GDALVectorGeomAbstractAlgorithm(const std::string &name, 87 : const std::string &description, 88 : const std::string &helpURL, 89 : bool standaloneStep, OptionsBase &opts); 90 : 91 : bool RunStep(GDALProgressFunc, void *) override; 92 : 93 : private: 94 : std::string &m_activeLayer; 95 : }; 96 : 97 : /************************************************************************/ 98 : /* GDALVectorGeomMakeValidAlgorithmLayer */ 99 : /************************************************************************/ 100 : 101 : template <class T> 102 : class GDALVectorGeomOneToOneAlgorithmLayer /* non final */ 103 : : public GDALVectorPipelineOutputLayer 104 : { 105 : public: 106 223 : OGRFeatureDefn *GetLayerDefn() override 107 : { 108 223 : return m_srcLayer.GetLayerDefn(); 109 : } 110 : 111 21 : GIntBig GetFeatureCount(int bForce) override 112 : { 113 21 : if (!m_poAttrQuery && !m_poFilterGeom) 114 11 : return m_srcLayer.GetFeatureCount(bForce); 115 10 : return OGRLayer::GetFeatureCount(bForce); 116 : } 117 : 118 12 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent, 119 : bool bForce) override 120 : { 121 12 : return m_srcLayer.GetExtent(iGeomField, psExtent, bForce); 122 : } 123 : 124 26 : OGRFeature *GetFeature(GIntBig nFID) override 125 : { 126 52 : auto poSrcFeature = 127 26 : std::unique_ptr<OGRFeature>(m_srcLayer.GetFeature(nFID)); 128 26 : if (!poSrcFeature) 129 11 : return nullptr; 130 15 : return TranslateFeature(std::move(poSrcFeature)).release(); 131 : } 132 : 133 47 : int TestCapability(const char *pszCap) override 134 : { 135 47 : if (EQUAL(pszCap, OLCRandomRead) || EQUAL(pszCap, OLCCurveGeometries) || 136 43 : EQUAL(pszCap, OLCMeasuredGeometries) || 137 39 : EQUAL(pszCap, OLCZGeometries) || EQUAL(pszCap, OLCFastGetExtent) || 138 34 : (EQUAL(pszCap, OLCFastFeatureCount) && !m_poAttrQuery && 139 4 : !m_poFilterGeom) || 140 30 : EQUAL(pszCap, OLCStringsAsUTF8)) 141 : { 142 33 : return m_srcLayer.TestCapability(pszCap); 143 : } 144 14 : return false; 145 : } 146 : 147 : protected: 148 : const typename T::Options m_opts; 149 : 150 40 : GDALVectorGeomOneToOneAlgorithmLayer(OGRLayer &oSrcLayer, 151 : const typename T::Options &opts) 152 40 : : GDALVectorPipelineOutputLayer(oSrcLayer), m_opts(opts) 153 : { 154 40 : SetDescription(oSrcLayer.GetDescription()); 155 40 : SetMetadata(oSrcLayer.GetMetadata()); 156 40 : if (!m_opts.m_geomField.empty()) 157 : { 158 2 : const int nIdx = oSrcLayer.GetLayerDefn()->GetGeomFieldIndex( 159 : m_opts.m_geomField.c_str()); 160 2 : if (nIdx >= 0) 161 2 : m_iGeomIdx = nIdx; 162 : else 163 0 : m_iGeomIdx = INT_MAX; 164 : } 165 40 : } 166 : 167 655 : bool IsSelectedGeomField(int idx) const 168 : { 169 655 : return m_iGeomIdx < 0 || idx == m_iGeomIdx; 170 : } 171 : 172 : virtual std::unique_ptr<OGRFeature> 173 : TranslateFeature(std::unique_ptr<OGRFeature> poSrcFeature) const = 0; 174 : 175 618 : void TranslateFeature( 176 : std::unique_ptr<OGRFeature> poSrcFeature, 177 : std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override 178 : { 179 1236 : auto poDstFeature = TranslateFeature(std::move(poSrcFeature)); 180 618 : if (poDstFeature) 181 616 : apoOutFeatures.push_back(std::move(poDstFeature)); 182 618 : } 183 : 184 : private: 185 : int m_iGeomIdx = -1; 186 : }; 187 : 188 : //! @endcond 189 : 190 : #endif /* GDALALG_VECTOR_GEOM_INCLUDED */