Coverage Report

Created: 2025-10-28 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/include/geos/noding/SegmentNodeList.h
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 2006      Refractions Research Inc.
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
 * Last port: noding/SegmentNodeList.java rev. 1.8 (JTS-1.10)
16
 *
17
 **********************************************************************/
18
19
#pragma once
20
21
#include <geos/export.h>
22
23
#include <cassert>
24
#include <iostream>
25
#include <vector>
26
#include <set>
27
#include <memory>
28
29
#include <geos/noding/SegmentNode.h> // for composition
30
31
#ifdef _MSC_VER
32
#pragma warning(push)
33
#pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class
34
#endif
35
36
// Forward declarations
37
namespace geos {
38
namespace geom {
39
class CoordinateSequence;
40
}
41
namespace noding {
42
class SegmentString;
43
class NodedSegmentString;
44
}
45
}
46
47
namespace geos {
48
namespace noding { // geos::noding
49
50
/** \brief
51
 * A list of the SegmentNode present along a
52
 * NodedSegmentString.
53
 */
54
class GEOS_DLL SegmentNodeList {
55
private:
56
    // Since we are adding frequently to the SegmentNodeList and
57
    // iterating infrequently, it is faster to store all the
58
    // SegmentNodes in a vector and sort/remove duplicates
59
    // before iteration, rather than storing them in a set
60
    // and continuously maintaining a sorted order.
61
    mutable std::vector<SegmentNode> nodeMap;
62
    mutable bool ready = false;
63
64
    bool constructZ;
65
    bool constructM;
66
67
    void prepare() const;
68
69
    // the parent edge
70
    const NodedSegmentString& edge;
71
72
    /**
73
     * Checks the correctness of the set of split edges corresponding
74
     * to this edge
75
     *
76
     * @param splitEdges the split edges for this edge (in order)
77
     */
78
    void checkSplitEdgesCorrectness(const std::vector<SegmentString*>& splitEdges) const;
79
80
    /**
81
     * Create a new "split edge" with the section of points between
82
     * (and including) the two intersections.
83
     * The label for the new edge is the same as the label for the
84
     * parent edge.
85
     *
86
     * ownership of return value is transferred
87
     */
88
    std::unique_ptr<SegmentString> createSplitEdge(const SegmentNode* ei0, const SegmentNode* ei1) const;
89
90
    /**
91
    * Extracts the points for a split edge running between two nodes.
92
    * The extracted points should contain no duplicate points.
93
    * There should always be at least two points extracted
94
    * (which will be the given nodes).
95
    *
96
    * @param ei0 the start node of the split edge
97
    * @param ei1 the end node of the split edge
98
    * @return the points for the split edge
99
    */
100
    std::unique_ptr<geom::CoordinateSequence> createSplitEdgePts(const SegmentNode* ei0, const SegmentNode* ei1) const;
101
102
    /**
103
     * Adds nodes for any collapsed edge pairs.
104
     * Collapsed edge pairs can be caused by inserted nodes, or they
105
     * can be pre-existing in the edge vertex list.
106
     * In order to provide the correct fully noded semantics,
107
     * the vertex at the base of a collapsed pair must also be added
108
     * as a node.
109
     */
110
    void addCollapsedNodes();
111
112
    /**
113
 /    * Adds nodes for any collapsed edge pairs
114
     * which are pre-existing in the vertex list.
115
     */
116
    void findCollapsesFromExistingVertices(
117
        std::vector<std::size_t>& collapsedVertexIndexes) const;
118
119
    /**
120
     * Adds nodes for any collapsed edge pairs caused by inserted nodes
121
     * Collapsed edge pairs occur when the same coordinate is inserted
122
     * as a node both before and after an existing edge vertex.
123
     * To provide the correct fully noded semantics,
124
     * the vertex must be added as a node as well.
125
     */
126
    void findCollapsesFromInsertedNodes(
127
        std::vector<std::size_t>& collapsedVertexIndexes) const;
128
129
    static bool findCollapseIndex(const SegmentNode& ei0, const SegmentNode& ei1,
130
                           size_t& collapsedVertexIndex);
131
132
    void addEdgeCoordinates(const SegmentNode* ei0, const SegmentNode* ei1, geom::CoordinateSequence& coordList) const;
133
134
public:
135
136
    // Declare type as noncopyable
137
    SegmentNodeList(const SegmentNodeList& other) = delete;
138
    SegmentNodeList& operator=(const SegmentNodeList& rhs) = delete;
139
140
    friend std::ostream& operator<< (std::ostream& os, const SegmentNodeList& l);
141
142
    using container = decltype(nodeMap);
143
    using iterator = container::iterator;
144
    using const_iterator = container::const_iterator;
145
146
    explicit SegmentNodeList(const NodedSegmentString& newEdge,
147
                             bool p_constructZ,
148
                             bool p_constructM)
149
67.5M
        : constructZ(p_constructZ)
150
67.5M
        , constructM(p_constructM)
151
67.5M
        , edge(newEdge) {}
152
153
67.5M
    ~SegmentNodeList() = default;
154
155
    const NodedSegmentString&
156
    getEdge() const
157
0
    {
158
0
        return edge;
159
0
    }
160
161
18.2k
    bool getConstructZ() const {
162
18.2k
        return constructZ;
163
18.2k
    }
164
165
18.2k
    bool getConstructM() const {
166
18.2k
        return constructM;
167
18.2k
    }
168
169
    /**
170
     * Adds an intersection into the list, if it isn't already there.
171
     * The input segmentIndex is expected to be normalized.
172
     *
173
     * @param intPt the intersection Coordinate, will be copied
174
     * @param segmentIndex
175
     */
176
    template<typename CoordType>
177
288M
    void add(const CoordType& intPt, std::size_t segmentIndex) {
178
        // Cast edge to SegmentString to avoid circular dependency between NodedSegmentString and SegmentNodeList
179
288M
        nodeMap.emplace_back(edge, intPt, segmentIndex, reinterpret_cast<const SegmentString&>(edge).getSegmentOctant(segmentIndex));
180
288M
        ready = false;
181
288M
    }
void geos::noding::SegmentNodeList::add<geos::geom::CoordinateXYZM>(geos::geom::CoordinateXYZM const&, unsigned long)
Line
Count
Source
177
206M
    void add(const CoordType& intPt, std::size_t segmentIndex) {
178
        // Cast edge to SegmentString to avoid circular dependency between NodedSegmentString and SegmentNodeList
179
206M
        nodeMap.emplace_back(edge, intPt, segmentIndex, reinterpret_cast<const SegmentString&>(edge).getSegmentOctant(segmentIndex));
180
206M
        ready = false;
181
206M
    }
void geos::noding::SegmentNodeList::add<geos::geom::Coordinate>(geos::geom::Coordinate const&, unsigned long)
Line
Count
Source
177
80.1M
    void add(const CoordType& intPt, std::size_t segmentIndex) {
178
        // Cast edge to SegmentString to avoid circular dependency between NodedSegmentString and SegmentNodeList
179
80.1M
        nodeMap.emplace_back(edge, intPt, segmentIndex, reinterpret_cast<const SegmentString&>(edge).getSegmentOctant(segmentIndex));
180
80.1M
        ready = false;
181
80.1M
    }
void geos::noding::SegmentNodeList::add<geos::geom::CoordinateXY>(geos::geom::CoordinateXY const&, unsigned long)
Line
Count
Source
177
1.71M
    void add(const CoordType& intPt, std::size_t segmentIndex) {
178
        // Cast edge to SegmentString to avoid circular dependency between NodedSegmentString and SegmentNodeList
179
1.71M
        nodeMap.emplace_back(edge, intPt, segmentIndex, reinterpret_cast<const SegmentString&>(edge).getSegmentOctant(segmentIndex));
180
1.71M
        ready = false;
181
1.71M
    }
182
183
    /// Return the number of nodes in this list
184
    size_t
185
    size() const
186
0
    {
187
0
        prepare();
188
0
        return nodeMap.size();
189
0
    }
190
191
3.82M
    iterator begin() {
192
3.82M
        prepare();
193
3.82M
        return nodeMap.begin();
194
3.82M
    }
195
196
3.79M
    const_iterator begin() const {
197
3.79M
        prepare();
198
3.79M
        return nodeMap.begin();
199
3.79M
    }
200
201
3.82M
    iterator end() {
202
3.82M
        prepare();
203
3.82M
        return nodeMap.end();
204
3.82M
    }
205
206
3.79M
    const_iterator end() const {
207
3.79M
        prepare();
208
3.79M
        return nodeMap.end();
209
3.79M
    }
210
211
    /**
212
     * Adds entries for the first and last points of the edge to the list
213
     */
214
    void addEndpoints();
215
216
    /**
217
     * Creates new edges for all the edges that the intersections in this
218
     * list split the parent edge into.
219
     * Adds the edges to the input list (this is so a single list
220
     * can be used to accumulate all split edges for a Geometry).
221
     */
222
    void addSplitEdges(std::vector<SegmentString*>& edgeList);
223
224
    void
225
    addSplitEdges(std::vector<SegmentString*>* edgeList)
226
3.79M
    {
227
        assert(edgeList);
228
3.79M
        addSplitEdges(*edgeList);
229
3.79M
    }
230
231
    /**
232
    * Gets the list of coordinates for the fully noded segment string,
233
    * including all original segment string vertices and vertices
234
    * introduced by nodes in this list.
235
    * Repeated coordinates are collapsed.
236
    *
237
    * @return an array of Coordinates
238
    *
239
    */
240
    std::unique_ptr<geom::CoordinateSequence> getSplitCoordinates();
241
242
243
};
244
245
std::ostream& operator<< (std::ostream& os, const SegmentNodeList& l);
246
247
} // namespace geos::noding
248
} // namespace geos
249
250
#ifdef _MSC_VER
251
#pragma warning(pop)
252
#endif
253