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 220 : const OGRFeatureDefn *GetLayerDefn() const override 60 : { 61 220 : 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 49 : int TestCapability(const char *pszCap) const override 87 : { 88 49 : if (EQUAL(pszCap, OLCRandomRead) || EQUAL(pszCap, OLCCurveGeometries) || 89 45 : EQUAL(pszCap, OLCMeasuredGeometries) || 90 41 : EQUAL(pszCap, OLCZGeometries) || EQUAL(pszCap, OLCFastGetExtent) || 91 36 : (EQUAL(pszCap, OLCFastFeatureCount) && !m_poAttrQuery && 92 4 : !m_poFilterGeom) || 93 32 : EQUAL(pszCap, OLCStringsAsUTF8)) 94 : { 95 33 : return m_srcLayer.TestCapability(pszCap); 96 : } 97 16 : return false; 98 : } 99 : 100 : protected: 101 : const typename T::Options m_opts; 102 : 103 63 : GDALVectorGeomOneToOneAlgorithmLayer(OGRLayer &oSrcLayer, 104 : const typename T::Options &opts) 105 63 : : GDALVectorPipelineOutputLayer(oSrcLayer), m_opts(opts) 106 : { 107 63 : SetDescription(oSrcLayer.GetDescription()); 108 63 : SetMetadata(oSrcLayer.GetMetadata()); 109 63 : 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 63 : } 119 : 120 737 : bool IsSelectedGeomField(int idx) const 121 : { 122 737 : 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 676 : void TranslateFeature( 129 : std::unique_ptr<OGRFeature> poSrcFeature, 130 : std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override 131 : { 132 1352 : auto poDstFeature = TranslateFeature(std::move(poSrcFeature)); 133 676 : if (poDstFeature) 134 674 : apoOutFeatures.push_back(std::move(poDstFeature)); 135 676 : } 136 : 137 : private: 138 : int m_iGeomIdx = -1; 139 : }; 140 : 141 : #ifdef HAVE_GEOS 142 : 143 : /************************************************************************/ 144 : /* GDALGeosNonStreamingAlgorithmLayer */ 145 : /************************************************************************/ 146 : 147 : /** A GDALGeosNonStreamingAlgorithmLayer manages the work of reading features 148 : * from an input layer, converting OGR geometries into GEOS geometries, 149 : * applying a GEOS function, and creating OGRFeatures for the results. It 150 : * appropriate only for GEOS algorithms that operate on all input geometries 151 : * at a single time. 152 : */ 153 : class GDALGeosNonStreamingAlgorithmLayer 154 : : public GDALVectorNonStreamingAlgorithmLayer 155 : { 156 : public: 157 : GDALGeosNonStreamingAlgorithmLayer(OGRLayer &srcLayer, int geomFieldIndex); 158 : 159 : ~GDALGeosNonStreamingAlgorithmLayer() override; 160 : 161 : void ResetReading() override; 162 : 163 : CPL_DISALLOW_COPY_ASSIGN(GDALGeosNonStreamingAlgorithmLayer) 164 : 165 : bool Process(GDALProgressFunc pfnProgress, void *pProgressData) override; 166 : 167 : std::unique_ptr<OGRFeature> GetNextProcessedFeature() override; 168 : 169 : virtual bool ProcessGeos() = 0; 170 : 171 : /// Whether the operation should fail if non-polygonal geometries are present 172 : virtual bool PolygonsOnly() const = 0; 173 : 174 : /// Whether empty result features should be excluded from the output 175 : virtual bool SkipEmpty() const = 0; 176 : 177 : protected: 178 : GEOSContextHandle_t m_poGeosContext{nullptr}; 179 : std::vector<GEOSGeometry *> m_apoGeosInputs{}; 180 : GEOSGeometry *m_poGeosResultAsCollection{nullptr}; 181 : GEOSGeometry **m_papoGeosResults{nullptr}; 182 : 183 : private: 184 : bool ConvertInputsToGeos(OGRLayer &srcLayer, int geomFieldIndex, 185 : GDALProgressFunc pfnProgress, void *pProgressData); 186 : 187 : void Cleanup(); 188 : 189 : std::vector<std::unique_ptr<OGRFeature>> m_apoFeatures{}; 190 : unsigned int m_nGeosResultSize{0}; 191 : unsigned int m_readPos{0}; 192 : }; 193 : 194 : #endif 195 : 196 : //! @endcond 197 : 198 : #endif /* GDALALG_VECTOR_GEOM_INCLUDED */