Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/apps/gdalalg_vector_geom.h
Line
Count
Source
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
    const OGRFeatureDefn *GetLayerDefn() const override
59
0
    {
60
0
        return m_srcLayer.GetLayerDefn();
61
0
    }
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSetGeomTypeAlgorithm>::GetLayerDefn() const
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSegmentizeAlgorithm>::GetLayerDefn() const
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSwapXYAlgorithm>::GetLayerDefn() const
62
63
    GIntBig GetFeatureCount(int bForce) override
64
0
    {
65
0
        if (!m_poAttrQuery && !m_poFilterGeom)
66
0
            return m_srcLayer.GetFeatureCount(bForce);
67
0
        return OGRLayer::GetFeatureCount(bForce);
68
0
    }
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSetGeomTypeAlgorithm>::GetFeatureCount(int)
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSegmentizeAlgorithm>::GetFeatureCount(int)
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSwapXYAlgorithm>::GetFeatureCount(int)
69
70
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
71
                      bool bForce) override
72
0
    {
73
0
        return m_srcLayer.GetExtent(iGeomField, psExtent, bForce);
74
0
    }
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSetGeomTypeAlgorithm>::IGetExtent(int, OGREnvelope*, bool)
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSegmentizeAlgorithm>::IGetExtent(int, OGREnvelope*, bool)
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSwapXYAlgorithm>::IGetExtent(int, OGREnvelope*, bool)
75
76
    OGRFeature *GetFeature(GIntBig nFID) override
77
0
    {
78
0
        auto poSrcFeature =
79
0
            std::unique_ptr<OGRFeature>(m_srcLayer.GetFeature(nFID));
80
0
        if (!poSrcFeature)
81
0
            return nullptr;
82
0
        return TranslateFeature(std::move(poSrcFeature)).release();
83
0
    }
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSetGeomTypeAlgorithm>::GetFeature(long long)
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSegmentizeAlgorithm>::GetFeature(long long)
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSwapXYAlgorithm>::GetFeature(long long)
84
85
    int TestCapability(const char *pszCap) const override
86
0
    {
87
0
        if (EQUAL(pszCap, OLCRandomRead) || EQUAL(pszCap, OLCCurveGeometries) ||
88
0
            EQUAL(pszCap, OLCMeasuredGeometries) ||
89
0
            EQUAL(pszCap, OLCZGeometries) || EQUAL(pszCap, OLCFastGetExtent) ||
90
0
            (EQUAL(pszCap, OLCFastFeatureCount) && !m_poAttrQuery &&
91
0
             !m_poFilterGeom) ||
92
0
            EQUAL(pszCap, OLCStringsAsUTF8))
93
0
        {
94
0
            return m_srcLayer.TestCapability(pszCap);
95
0
        }
96
0
        return false;
97
0
    }
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSetGeomTypeAlgorithm>::TestCapability(char const*) const
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSegmentizeAlgorithm>::TestCapability(char const*) const
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSwapXYAlgorithm>::TestCapability(char const*) const
98
99
  protected:
100
    const typename T::Options m_opts;
101
102
    GDALVectorGeomOneToOneAlgorithmLayer(OGRLayer &oSrcLayer,
103
                                         const typename T::Options &opts)
104
0
        : GDALVectorPipelineOutputLayer(oSrcLayer), m_opts(opts)
105
0
    {
106
0
        SetDescription(oSrcLayer.GetDescription());
107
0
        SetMetadata(oSrcLayer.GetMetadata());
108
0
        if (!m_opts.m_geomField.empty())
109
0
        {
110
0
            const int nIdx = oSrcLayer.GetLayerDefn()->GetGeomFieldIndex(
111
0
                m_opts.m_geomField.c_str());
112
0
            if (nIdx >= 0)
113
0
                m_iGeomIdx = nIdx;
114
0
            else
115
0
                m_iGeomIdx = INT_MAX;
116
0
        }
117
0
    }
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSetGeomTypeAlgorithm>::GDALVectorGeomOneToOneAlgorithmLayer(OGRLayer&, GDALVectorSetGeomTypeAlgorithm::Options const&)
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSegmentizeAlgorithm>::GDALVectorGeomOneToOneAlgorithmLayer(OGRLayer&, GDALVectorSegmentizeAlgorithm::Options const&)
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSwapXYAlgorithm>::GDALVectorGeomOneToOneAlgorithmLayer(OGRLayer&, GDALVectorSwapXYAlgorithm::Options const&)
118
119
    bool IsSelectedGeomField(int idx) const
120
0
    {
121
0
        return m_iGeomIdx < 0 || idx == m_iGeomIdx;
122
0
    }
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSetGeomTypeAlgorithm>::IsSelectedGeomField(int) const
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSegmentizeAlgorithm>::IsSelectedGeomField(int) const
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSwapXYAlgorithm>::IsSelectedGeomField(int) const
123
124
    virtual std::unique_ptr<OGRFeature>
125
    TranslateFeature(std::unique_ptr<OGRFeature> poSrcFeature) const = 0;
126
127
    void TranslateFeature(
128
        std::unique_ptr<OGRFeature> poSrcFeature,
129
        std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override
130
0
    {
131
0
        auto poDstFeature = TranslateFeature(std::move(poSrcFeature));
132
0
        if (poDstFeature)
133
0
            apoOutFeatures.push_back(std::move(poDstFeature));
134
0
    }
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSetGeomTypeAlgorithm>::TranslateFeature(std::__1::unique_ptr<OGRFeature, std::__1::default_delete<OGRFeature> >, std::__1::vector<std::__1::unique_ptr<OGRFeature, std::__1::default_delete<OGRFeature> >, std::__1::allocator<std::__1::unique_ptr<OGRFeature, std::__1::default_delete<OGRFeature> > > >&)
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSegmentizeAlgorithm>::TranslateFeature(std::__1::unique_ptr<OGRFeature, std::__1::default_delete<OGRFeature> >, std::__1::vector<std::__1::unique_ptr<OGRFeature, std::__1::default_delete<OGRFeature> >, std::__1::allocator<std::__1::unique_ptr<OGRFeature, std::__1::default_delete<OGRFeature> > > >&)
Unexecuted instantiation: GDALVectorGeomOneToOneAlgorithmLayer<GDALVectorSwapXYAlgorithm>::TranslateFeature(std::__1::unique_ptr<OGRFeature, std::__1::default_delete<OGRFeature> >, std::__1::vector<std::__1::unique_ptr<OGRFeature, std::__1::default_delete<OGRFeature> >, std::__1::allocator<std::__1::unique_ptr<OGRFeature, std::__1::default_delete<OGRFeature> > > >&)
135
136
  private:
137
    int m_iGeomIdx = -1;
138
};
139
140
#ifdef HAVE_GEOS
141
142
/************************************************************************/
143
/*                  GDALGeosNonStreamingAlgorithmLayer                  */
144
/************************************************************************/
145
146
/** A GDALGeosNonStreamingAlgorithmLayer manages the work of reading features
147
 *  from an input layer, converting OGR geometries into GEOS geometries,
148
 *  applying a GEOS function, and creating OGRFeatures for the results. It
149
 *  appropriate only for GEOS algorithms that operate on all input geometries
150
 *  at a single time.
151
 */
152
class GDALGeosNonStreamingAlgorithmLayer
153
    : public GDALVectorNonStreamingAlgorithmLayer
154
{
155
  public:
156
    GDALGeosNonStreamingAlgorithmLayer(OGRLayer &srcLayer, int geomFieldIndex);
157
158
    ~GDALGeosNonStreamingAlgorithmLayer() override;
159
160
    void ResetReading() override;
161
162
    CPL_DISALLOW_COPY_ASSIGN(GDALGeosNonStreamingAlgorithmLayer)
163
164
    bool Process(GDALProgressFunc pfnProgress, void *pProgressData) override;
165
166
    std::unique_ptr<OGRFeature> GetNextProcessedFeature() override;
167
168
    virtual bool ProcessGeos() = 0;
169
170
    /// Whether the operation should fail if non-polygonal geometries are present
171
    virtual bool PolygonsOnly() const = 0;
172
173
    /// Whether empty result features should be excluded from the output
174
    virtual bool SkipEmpty() const = 0;
175
176
  protected:
177
    GEOSContextHandle_t m_poGeosContext{nullptr};
178
    std::vector<GEOSGeometry *> m_apoGeosInputs{};
179
    GEOSGeometry *m_poGeosResultAsCollection{nullptr};
180
    GEOSGeometry **m_papoGeosResults{nullptr};
181
182
  private:
183
    bool ConvertInputsToGeos(OGRLayer &srcLayer, int geomFieldIndex,
184
                             GDALProgressFunc pfnProgress, void *pProgressData);
185
186
    void Cleanup();
187
188
    std::vector<std::unique_ptr<OGRFeature>> m_apoFeatures{};
189
    unsigned int m_nGeosResultSize{0};
190
    unsigned int m_readPos{0};
191
};
192
193
#endif
194
195
//! @endcond
196
197
#endif /* GDALALG_VECTOR_GEOM_INCLUDED */