LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_geom.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 39 40 97.5 %
Date: 2026-06-03 12:46:18 Functions: 50 72 69.4 %

          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 */

Generated by: LCOV version 1.14