/src/geos/include/geos/coverage/CoverageRingEdges.h
Line | Count | Source |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (C) 2023 Paul Ramsey <pramsey@cleverelephant.ca> |
7 | | * Copyright (c) 2023 Martin Davis. |
8 | | * |
9 | | * This is free software; you can redistribute and/or modify it under |
10 | | * the terms of the GNU Lesser General Public Licence as published |
11 | | * by the Free Software Foundation. |
12 | | * See the COPYING file for more information. |
13 | | * |
14 | | **********************************************************************/ |
15 | | |
16 | | #pragma once |
17 | | |
18 | | #include <geos/geom/Coordinate.h> |
19 | | #include <geos/geom/LineSegment.h> |
20 | | #include <geos/coverage/CoverageEdge.h> // to materialize CoverageEdge |
21 | | |
22 | | #include <set> |
23 | | #include <map> |
24 | | |
25 | | // Forward declarations |
26 | | namespace geos { |
27 | | namespace geom { |
28 | | class CoordinateSequence; |
29 | | class Geometry; |
30 | | class LinearRing; |
31 | | class MultiPolygon; |
32 | | class Polygon; |
33 | | } |
34 | | namespace coverage { |
35 | | class CoverageEdge; |
36 | | } |
37 | | } |
38 | | |
39 | | namespace geos { // geos |
40 | | namespace coverage { // geos.coverage |
41 | | |
42 | | /** |
43 | | * Models a polygonal coverage as a set of unique {@link CoverageEdge}s, |
44 | | * linked to the parent rings in the coverage polygons. |
45 | | * Each edge has either one or two parent rings, depending on whether |
46 | | * it is an inner or outer edge of the coverage. |
47 | | * The source coverage is represented as a array of polygonal geometries |
48 | | * (either {@link geos::geom::Polygon}s or {@link geos::geom::MultiPolygon}s). |
49 | | * |
50 | | * @author Martin Davis |
51 | | */ |
52 | | class GEOS_DLL CoverageRingEdges { |
53 | | using Coordinate = geos::geom::Coordinate; |
54 | | using CoordinateSequence = geos::geom::CoordinateSequence; |
55 | | using Geometry = geos::geom::Geometry; |
56 | | using LinearRing = geos::geom::LinearRing; |
57 | | using LineSegment = geos::geom::LineSegment; |
58 | | using MultiPolygon = geos::geom::MultiPolygon; |
59 | | using Polygon = geos::geom::Polygon; |
60 | | |
61 | | private: |
62 | | |
63 | | // Members |
64 | | const std::vector<const Geometry*>& m_coverage; |
65 | | std::map<const LinearRing*, std::vector<CoverageEdge*>> m_ringEdgesMap; |
66 | | std::vector<CoverageEdge*> m_edges; |
67 | | std::vector<std::unique_ptr<CoverageEdge>> m_edgeStore; |
68 | | |
69 | | /* Turn off copy constructors for MSVC */ |
70 | | CoverageRingEdges(const CoverageRingEdges&) = delete; |
71 | | CoverageRingEdges& operator=(const CoverageRingEdges&) = delete; |
72 | | |
73 | | public: |
74 | | |
75 | | CoverageRingEdges(const std::vector<const Geometry*>& coverage) |
76 | 0 | : m_coverage(coverage) |
77 | 0 | { |
78 | 0 | build(); |
79 | 0 | }; |
80 | | |
81 | | |
82 | | std::vector<CoverageEdge*>& getEdges() |
83 | 0 | { |
84 | 0 | return m_edges; |
85 | 0 | }; |
86 | | |
87 | | /** |
88 | | * Selects the edges with a given ring count (which can be 1 or 2). |
89 | | * |
90 | | * @param ringCount the edge ring count to select (1 or 2) |
91 | | * @return the selected edges |
92 | | */ |
93 | | std::vector<CoverageEdge*> selectEdges( |
94 | | std::size_t ringCount) const; |
95 | | |
96 | | /** |
97 | | * Recreates the polygon coverage from the current edge values. |
98 | | * |
99 | | * @return an array of polygonal geometries representing the coverage |
100 | | */ |
101 | | std::vector<std::unique_ptr<Geometry>> buildCoverage() const; |
102 | | |
103 | | |
104 | | private: |
105 | | |
106 | | void build(); |
107 | | |
108 | | void addRingEdges( |
109 | | const LinearRing* ring, |
110 | | Coordinate::UnorderedSet& nodes, |
111 | | LineSegment::UnorderedSet& boundarySegs, |
112 | | std::map<LineSegment, CoverageEdge*>& uniqueEdgeMap); |
113 | | |
114 | | void addBoundaryInnerNodes( |
115 | | const LinearRing* ring, |
116 | | LineSegment::UnorderedSet& boundarySegs, |
117 | | Coordinate::UnorderedSet& nodes); |
118 | | |
119 | | std::vector<CoverageEdge*> extractRingEdges( |
120 | | const LinearRing* ring, |
121 | | std::map<LineSegment, CoverageEdge*>& uniqueEdgeMap, |
122 | | Coordinate::UnorderedSet& nodes); |
123 | | |
124 | | CoverageEdge* createEdge( |
125 | | const CoordinateSequence& ring, |
126 | | std::map<LineSegment, CoverageEdge*>& uniqueEdgeMap); |
127 | | |
128 | | CoverageEdge* createEdge( |
129 | | const CoordinateSequence& ring, |
130 | | std::size_t start, std::size_t end, |
131 | | std::map<LineSegment, CoverageEdge*>& uniqueEdgeMap); |
132 | | |
133 | | std::size_t findNextNodeIndex( |
134 | | const CoordinateSequence& ring, |
135 | | std::size_t start, |
136 | | Coordinate::UnorderedSet& nodes) const; |
137 | | |
138 | | static std::size_t next( |
139 | | std::size_t index, |
140 | | const CoordinateSequence& ring); |
141 | | |
142 | | Coordinate::UnorderedSet findMultiRingNodes( |
143 | | const std::vector<const Geometry*>& coverage); |
144 | | |
145 | | Coordinate::UnorderedSet findBoundaryNodes( |
146 | | LineSegment::UnorderedSet& lineSegments); |
147 | | |
148 | | std::unique_ptr<Geometry> buildPolygonal( |
149 | | const Geometry* geom) const; |
150 | | |
151 | | std::unique_ptr<Geometry> buildMultiPolygon( |
152 | | const MultiPolygon* geom) const; |
153 | | |
154 | | std::unique_ptr<Polygon> buildPolygon( |
155 | | const Polygon* polygon) const; |
156 | | |
157 | | std::unique_ptr<LinearRing> buildRing( |
158 | | const LinearRing* ring) const; |
159 | | |
160 | | bool isEdgeDirForward( |
161 | | const std::vector<CoverageEdge*>& ringEdges, |
162 | | std::size_t index, |
163 | | const Coordinate& prevPt) const; |
164 | | |
165 | | |
166 | | }; |
167 | | |
168 | | } // namespace geos.coverage |
169 | | } // namespace geos |