Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: Base classes for some geometry-related vector algorithms 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 : #include "ogr_geos.h" 18 : 19 : //! @cond Doxygen_Suppress 20 : 21 : /************************************************************************/ 22 : /* GDALVectorGeomAbstractAlgorithm */ 23 : /************************************************************************/ 24 : 25 : class GDALVectorGeomAbstractAlgorithm /* non final */ 26 : : public GDALVectorPipelineStepAlgorithm 27 : { 28 : protected: 29 : struct OptionsBase 30 : { 31 : std::string m_activeLayer{}; 32 : std::string m_geomField{}; 33 : }; 34 : 35 : virtual std::unique_ptr<OGRLayerWithTranslateFeature> 36 : CreateAlgLayer(OGRLayer &srcLayer) = 0; 37 : 38 : GDALVectorGeomAbstractAlgorithm(const std::string &name, 39 : const std::string &description, 40 : const std::string &helpURL, 41 : bool standaloneStep, OptionsBase &opts); 42 : 43 : bool RunStep(GDALPipelineStepRunContext &ctxt) override; 44 : 45 : private: 46 : std::string &m_activeLayer; 47 : }; 48 : 49 : /************************************************************************/ 50 : /* GDALVectorGeomOneToOneAlgorithmLayer */ 51 : /************************************************************************/ 52 : 53 : template <class T> 54 : class GDALVectorGeomOneToOneAlgorithmLayer /* non final */ 55 : : public GDALVectorPipelineOutputLayer 56 : { 57 : public: 58 220 : const OGRFeatureDefn *GetLayerDefn() const override 59 : { 60 220 : return m_srcLayer.GetLayerDefn(); 61 : } 62 : 63 21 : GIntBig GetFeatureCount(int bForce) override 64 : { 65 21 : if (!m_poAttrQuery && !m_poFilterGeom) 66 11 : return m_srcLayer.GetFeatureCount(bForce); 67 10 : return OGRLayer::GetFeatureCount(bForce); 68 : } 69 : 70 12 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent, 71 : bool bForce) override 72 : { 73 12 : return m_srcLayer.GetExtent(iGeomField, psExtent, bForce); 74 : } 75 : 76 26 : OGRFeature *GetFeature(GIntBig nFID) override 77 : { 78 52 : auto poSrcFeature = 79 26 : std::unique_ptr<OGRFeature>(m_srcLayer.GetFeature(nFID)); 80 26 : if (!poSrcFeature) 81 11 : return nullptr; 82 15 : return TranslateFeature(std::move(poSrcFeature)).release(); 83 : } 84 : 85 48 : int TestCapability(const char *pszCap) const override 86 : { 87 48 : if (EQUAL(pszCap, OLCRandomRead) || EQUAL(pszCap, OLCCurveGeometries) || 88 44 : EQUAL(pszCap, OLCMeasuredGeometries) || 89 40 : EQUAL(pszCap, OLCZGeometries) || EQUAL(pszCap, OLCFastGetExtent) || 90 35 : (EQUAL(pszCap, OLCFastFeatureCount) && !m_poAttrQuery && 91 4 : !m_poFilterGeom) || 92 31 : EQUAL(pszCap, OLCStringsAsUTF8)) 93 : { 94 33 : return m_srcLayer.TestCapability(pszCap); 95 : } 96 15 : return false; 97 : } 98 : 99 : protected: 100 : const typename T::Options m_opts; 101 : 102 43 : GDALVectorGeomOneToOneAlgorithmLayer(OGRLayer &oSrcLayer, 103 : const typename T::Options &opts) 104 43 : : GDALVectorPipelineOutputLayer(oSrcLayer), m_opts(opts) 105 : { 106 43 : SetDescription(oSrcLayer.GetDescription()); 107 43 : SetMetadata(oSrcLayer.GetMetadata()); 108 43 : if (!m_opts.m_geomField.empty()) 109 : { 110 2 : const int nIdx = oSrcLayer.GetLayerDefn()->GetGeomFieldIndex( 111 : m_opts.m_geomField.c_str()); 112 2 : if (nIdx >= 0) 113 2 : m_iGeomIdx = nIdx; 114 : else 115 0 : m_iGeomIdx = INT_MAX; 116 : } 117 43 : } 118 : 119 686 : bool IsSelectedGeomField(int idx) const 120 : { 121 686 : return m_iGeomIdx < 0 || idx == m_iGeomIdx; 122 : } 123 : 124 : virtual std::unique_ptr<OGRFeature> 125 : TranslateFeature(std::unique_ptr<OGRFeature> poSrcFeature) const = 0; 126 : 127 641 : void TranslateFeature( 128 : std::unique_ptr<OGRFeature> poSrcFeature, 129 : std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override 130 : { 131 1282 : auto poDstFeature = TranslateFeature(std::move(poSrcFeature)); 132 641 : if (poDstFeature) 133 639 : apoOutFeatures.push_back(std::move(poDstFeature)); 134 641 : } 135 : 136 : private: 137 : int m_iGeomIdx = -1; 138 : }; 139 : 140 : #ifdef HAVE_GEOS 141 : 142 : /************************************************************************/ 143 : /* GDALGeosNonStreamingAlgorithmDataset */ 144 : /************************************************************************/ 145 : 146 : /** A GDALGeosNonStreamingAlgorithmDataset manages the work of reading features 147 : * from an input layer, converting OGR geometries into GEOS geometries, 148 : * applying a GEOS function, and writing result to an output layer. It is 149 : * appropriate only for GEOS algorithms that operate on all input geometries 150 : * at a single time. 151 : */ 152 : class GDALGeosNonStreamingAlgorithmDataset 153 : : public GDALVectorNonStreamingAlgorithmDataset 154 : { 155 : public: 156 : GDALGeosNonStreamingAlgorithmDataset(); 157 : 158 : ~GDALGeosNonStreamingAlgorithmDataset() override; 159 : 160 : CPL_DISALLOW_COPY_ASSIGN(GDALGeosNonStreamingAlgorithmDataset) 161 : 162 : bool Process(OGRLayer &srcLayer, OGRLayer &dstLayer, int geomFieldIndex, 163 : GDALProgressFunc pfnProgress, void *pProgressData) override; 164 : 165 : virtual bool ProcessGeos() = 0; 166 : 167 : /// Whether the operation should fail if non-polygonal geometries are present 168 : virtual bool PolygonsOnly() const = 0; 169 : 170 : /// Whether empty result features should be excluded from the output 171 : virtual bool SkipEmpty() const = 0; 172 : 173 : protected: 174 : GEOSContextHandle_t m_poGeosContext{nullptr}; 175 : std::vector<GEOSGeometry *> m_apoGeosInputs{}; 176 : GEOSGeometry *m_poGeosResultAsCollection{nullptr}; 177 : GEOSGeometry **m_papoGeosResults{nullptr}; 178 : 179 : private: 180 : bool ConvertInputsToGeos(OGRLayer &srcLayer, OGRLayer &dstLayer, 181 : int geomFieldIndex, bool sameDefn, 182 : GDALProgressFunc pfnProgress, void *pProgressData); 183 : 184 : bool ConvertOutputsFromGeos(OGRLayer &dstLayer, 185 : GDALProgressFunc pfnProgress, 186 : void *pProgressData, double dfProgressStart, 187 : double dfProgressRatio); 188 : 189 : void Cleanup(); 190 : 191 : std::vector<std::unique_ptr<OGRFeature>> m_apoFeatures{}; 192 : unsigned int m_nGeosResultSize{0}; 193 : }; 194 : 195 : #endif 196 : 197 : //! @endcond 198 : 199 : #endif /* GDALALG_VECTOR_GEOM_INCLUDED */