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