Coverage Report

Created: 2025-11-08 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/include/geos/simplify/RingHull.h
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 2021 Paul Ramsey <pramsey@cleverelephant.ca>
7
 *
8
 * This is free software; you can redistribute and/or modify it under
9
 * the terms of the GNU Lesser General Public Licence as published
10
 * by the Free Software Foundation.
11
 * See the COPYING file for more information.
12
 *
13
 **********************************************************************/
14
15
#pragma once
16
17
#include <geos/geom/Coordinate.h>
18
#include <geos/simplify/LinkedRing.h>
19
#include <geos/index/VertexSequencePackedRtree.h>
20
21
#include <queue>
22
23
namespace geos {
24
namespace geom {
25
class Envelope;
26
class LinearRing;
27
class LineString;
28
class Polygon;
29
}
30
namespace simplify {
31
class RingHullIndex;
32
}
33
}
34
35
namespace geos {
36
namespace simplify { // geos::simplify
37
38
39
class RingHull
40
{
41
    using Coordinate = geos::geom::Coordinate;
42
    using CoordinateSequence = geos::geom::CoordinateSequence;
43
    using Envelope = geos::geom::Envelope;
44
    using LinearRing = geos::geom::LinearRing;
45
    using LineString = geos::geom::LineString;
46
    using Polygon = geos::geom::Polygon;
47
    using VertexSequencePackedRtree = geos::index::VertexSequencePackedRtree;
48
49
50
public:
51
52
    /*
53
    * Creates a new instance.
54
    *
55
    * @param p_ring the ring vertices to process
56
    * @param p_isOuter whether the hull is outer or inner
57
    */
58
    RingHull(const LinearRing* p_ring, bool p_isOuter);
59
60
    void setMinVertexNum(std::size_t minVertexNum);
61
62
    void setMaxAreaDelta(double maxAreaDelta);
63
64
    const Envelope* getEnvelope() const;
65
66
    std::unique_ptr<LinearRing> getHull(RingHullIndex& hullIndex);
67
68
    static bool isConvex(const LinkedRing& vertexRing, std::size_t index);
69
70
    static double area(const LinkedRing& vertexRing, std::size_t index);
71
72
    void compute(RingHullIndex& hullIndex);
73
74
    std::unique_ptr<Polygon> toGeometry() const;
75
76
77
private:
78
79
80
    class Corner
81
    {
82
83
    private:
84
85
        std::size_t index;
86
        std::size_t prev;
87
        std::size_t next;
88
        double area;
89
90
    public:
91
92
        Corner(std::size_t p_idx, std::size_t p_prev, std::size_t p_next, double p_area)
93
0
            : index(p_idx)
94
0
            , prev(p_prev)
95
0
            , next(p_next)
96
0
            , area(p_area)
97
0
            {};
98
99
0
        inline int compareTo(const Corner& rhs) const {
100
0
            if (area == rhs.getArea()) {
101
0
                if (index == rhs.getIndex())
102
0
                    return 0;
103
0
                else return index < rhs.getIndex() ? -1 : 1;
104
0
            }
105
0
            else return area < rhs.getArea() ? -1 : 1;
106
0
        }
107
108
0
        inline bool operator< (const Corner& rhs) const {
109
0
            return compareTo(rhs) < 0;
110
0
        };
111
112
0
        inline bool operator> (const Corner& rhs) const {
113
0
            return compareTo(rhs) > 0;
114
0
        };
115
116
0
        inline bool operator==(const Corner& rhs) const {
117
0
            return compareTo(rhs) == 0;
118
0
        };
119
120
        bool isVertex(std::size_t p_index) const;
121
        std::size_t getIndex() const;
122
        double getArea() const;
123
        void envelope(const LinkedRing& ring, Envelope& env) const;
124
        bool intersects(const Coordinate& v, const LinkedRing& ring) const;
125
        bool isRemoved(const LinkedRing& ring) const;
126
        std::unique_ptr<LineString> toLineString(const LinkedRing& ring);
127
128
        struct Greater {
129
0
            inline bool operator()(const Corner & a, const Corner & b) const {
130
0
                return a > b;
131
0
            }
132
        };
133
134
        using PriorityQueue = std::priority_queue<Corner, std::vector<Corner>, Corner::Greater>;
135
136
    }; // class Corner
137
138
139
140
    const LinearRing* inputRing;
141
    double targetVertexNum = -1.0;
142
    double targetAreaDelta = -1.0;
143
144
    /**
145
    * The polygon vertices are provided in CW orientation.
146
    * Thus for convex interior angles
147
    * the vertices forming the angle are in CW orientation.
148
    */
149
    std::unique_ptr<CoordinateSequence> vertex;
150
    std::unique_ptr<LinkedRing> vertexRing;
151
    double areaDelta = 0;
152
153
    /**
154
    * Indexing vertices improves corner intersection testing performance.
155
    * The ring vertices are contiguous, so are suitable for a
156
    * {@link VertexSequencePackedRtree}.
157
    */
158
    std::unique_ptr<VertexSequencePackedRtree> vertexIndex;
159
160
    Corner::PriorityQueue cornerQueue;
161
162
163
    void init(CoordinateSequence& ring, bool isOuter);
164
    void addCorner(std::size_t i, Corner::PriorityQueue& cornerQueue);
165
    bool isAtTarget(const Corner& corner);
166
167
    /**
168
    * Removes a corner by removing the apex vertex from the ring.
169
    * Two new corners are created with apexes
170
    * at the other vertices of the corner
171
    * (if they are non-convex and thus removable).
172
    *
173
    * @param corner the corner to remove
174
    * @param cornerQueue the corner queue
175
    */
176
    void removeCorner(const Corner& corner, Corner::PriorityQueue& cornerQueue);
177
    bool isRemovable(const Corner& corner, const RingHullIndex& hullIndex) const;
178
179
    /**
180
    * Tests if any vertices in a hull intersect the corner triangle.
181
    * Uses the vertex spatial index for efficiency.
182
    *
183
    * @param corner the corner vertices
184
    * @param cornerEnv the envelope of the corner
185
    * @param hull the hull to test
186
    * @return true if there is an intersecting vertex
187
    */
188
    bool hasIntersectingVertex(
189
        const Corner& corner,
190
        const Envelope& cornerEnv,
191
        const RingHull* hull) const;
192
193
    const Coordinate& getCoordinate(std::size_t index) const;
194
195
    void query(
196
        const Envelope& cornerEnv,
197
        std::vector<std::size_t>& result) const;
198
199
    void queryHull(const Envelope& queryEnv, std::vector<Coordinate>& pts);
200
201
202
203
204
}; // RingHull
205
206
207
} // geos::simplify
208
} // geos