1 /**********************************************************************
2 *
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
5 *
6 * Copyright (C) 2020 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 #include <geos/operation/overlayng/MaximalEdgeRing.h>
16 #include <geos/operation/overlayng/OverlayEdge.h>
17 #include <geos/operation/overlayng/OverlayLabel.h>
18 #include <geos/operation/overlayng/OverlayEdgeRing.h>
19 #include <geos/geom/Location.h>
20 #include <geos/geom/Coordinate.h>
21 #include <geos/geom/CoordinateSequence.h>
22 #include <geos/geom/CoordinateArraySequence.h>
23
24 namespace geos { // geos
25 namespace operation { // geos.operation
26 namespace overlayng { // geos.operation.overlayng
27
28 using namespace geos::geom;
29
30 /*public*/
31 bool
isForward() const32 OverlayEdge::isForward() const
33 {
34 return direction;
35 }
36
37 /*public*/
38 const Coordinate&
directionPt() const39 OverlayEdge::directionPt() const
40 {
41 return dirPt;
42 }
43
44 /*public*/
45 OverlayLabel*
getLabel() const46 OverlayEdge::getLabel() const
47 {
48 return label;
49 }
50
51 /*public*/
52 Location
getLocation(int index,int position) const53 OverlayEdge::getLocation(int index, int position) const
54 {
55 return label->getLocation(index, position, direction);
56 }
57
58 /*public*/
59 const Coordinate&
getCoordinate() const60 OverlayEdge::getCoordinate() const
61 {
62 return orig();
63 }
64
65 /*public*/
66 const CoordinateSequence*
getCoordinatesRO() const67 OverlayEdge::getCoordinatesRO() const
68 {
69 return pts;
70 }
71
72 /*public*/
73 std::unique_ptr<CoordinateSequence>
getCoordinates()74 OverlayEdge::OverlayEdge::getCoordinates()
75 {
76 // return a copy of pts
77 return pts->clone();
78 }
79
80 /*public*/
81 std::unique_ptr<CoordinateSequence>
getCoordinatesOriented()82 OverlayEdge::getCoordinatesOriented()
83 {
84 if (direction) {
85 return pts->clone();
86 }
87 std::unique_ptr<CoordinateSequence> ptsCopy = pts->clone();
88 CoordinateSequence::reverse(ptsCopy.get());
89 return ptsCopy;
90 }
91
92 /**
93 * Adds the coordinates of this edge to the given list,
94 * in the direction of the edge.
95 * Duplicate coordinates are removed
96 * (which means that this is safe to use for a path
97 * of connected edges in the topology graph).
98 *
99 * @param coords the coordinate list to add to
100 */
101 /*public*/
102 void
addCoordinates(CoordinateArraySequence * coords)103 OverlayEdge::addCoordinates(CoordinateArraySequence* coords)
104 {
105 bool isFirstEdge = coords->size() > 0;
106 if (direction) {
107 int startIndex = 1;
108 if (isFirstEdge) {
109 startIndex = 0;
110 }
111 for (std::size_t i = startIndex, sz = pts->size(); i < sz; i++) {
112 coords->add(pts->getAt(i), false);
113 }
114 }
115 else { // is backward
116 int startIndex = (int)(pts->size()) - 2;
117 if (isFirstEdge) {
118 startIndex = (int)(pts->size()) - 1;
119 }
120 for (int i = startIndex; i >= 0; i--) {
121 coords->add(pts->getAt(i), false);
122 }
123 }
124 }
125
126 /*public*/
127 OverlayEdge*
symOE() const128 OverlayEdge::symOE() const
129 {
130 return static_cast<OverlayEdge*>(sym());
131 }
132
133 /*public*/
134 OverlayEdge*
oNextOE() const135 OverlayEdge::oNextOE() const
136 {
137 return static_cast<OverlayEdge*>(oNext());
138 }
139
140 /*public*/
141 bool
isInResultArea() const142 OverlayEdge::isInResultArea() const
143 {
144 return m_isInResultArea;
145 }
146
147 /*public*/
148 bool
isInResultAreaBoth() const149 OverlayEdge::isInResultAreaBoth() const
150 {
151 return m_isInResultArea && symOE()->m_isInResultArea;
152 }
153
154 /*public*/
155 bool
isInResultEither() const156 OverlayEdge::isInResultEither() const
157 {
158 return isInResult() || symOE()->isInResult();
159 }
160
161 /*public*/
162 void
unmarkFromResultAreaBoth()163 OverlayEdge::unmarkFromResultAreaBoth()
164 {
165 m_isInResultArea = false;
166 symOE()->m_isInResultArea = false;
167 }
168
169 /*public*/
170 void
markInResultArea()171 OverlayEdge::markInResultArea()
172 {
173 m_isInResultArea = true;
174 }
175
176 /*public*/
177 void
markInResultAreaBoth()178 OverlayEdge::markInResultAreaBoth()
179 {
180 m_isInResultArea = true;
181 symOE()->m_isInResultArea = true;
182 }
183
184 /*public*/
185 bool
isInResultLine() const186 OverlayEdge::isInResultLine() const
187 {
188 return m_isInResultLine;
189 }
190
191 /*public*/
192 void
markInResultLine()193 OverlayEdge::markInResultLine()
194 {
195 m_isInResultLine = true;
196 symOE()->m_isInResultLine = true;
197 }
198
199 /*public*/
200 bool
isInResult() const201 OverlayEdge::isInResult() const
202 {
203 return m_isInResultArea || m_isInResultLine;
204 }
205
206 void
setNextResult(OverlayEdge * e)207 OverlayEdge::setNextResult(OverlayEdge* e)
208 {
209 // Assert: e.orig() == this.dest();
210 nextResultEdge = e;
211 }
212
213 /*public*/
214 OverlayEdge*
nextResult() const215 OverlayEdge::nextResult() const
216 {
217 return nextResultEdge;
218 }
219
220 /*public*/
221 bool
isResultLinked() const222 OverlayEdge::isResultLinked() const
223 {
224 return nextResultEdge != nullptr;
225 }
226
227 void
setNextResultMax(OverlayEdge * e)228 OverlayEdge::setNextResultMax(OverlayEdge* e)
229 {
230 // Assert: e.orig() == this.dest();
231 nextResultMaxEdge = e;
232 }
233
234 /*public*/
235 OverlayEdge*
nextResultMax() const236 OverlayEdge::nextResultMax() const
237 {
238 return nextResultMaxEdge;
239 }
240
241 /*public*/
242 bool
isResultMaxLinked() const243 OverlayEdge::isResultMaxLinked() const
244 {
245 return nextResultMaxEdge != nullptr;
246 }
247
248 /*public*/
249 bool
isVisited() const250 OverlayEdge::isVisited() const
251 {
252 return m_isVisited;
253 }
254
255 /*private*/
256 void
markVisited()257 OverlayEdge::markVisited()
258 {
259 m_isVisited = true;
260 }
261
262 /*public*/
263 void
markVisitedBoth()264 OverlayEdge::markVisitedBoth()
265 {
266 markVisited();
267 symOE()->markVisited();
268 }
269
270 /*public*/
271 void
setEdgeRing(const OverlayEdgeRing * p_edgeRing)272 OverlayEdge::setEdgeRing(const OverlayEdgeRing* p_edgeRing)
273 {
274 edgeRing = p_edgeRing;
275 }
276
277 /*public*/
278 const OverlayEdgeRing*
getEdgeRing() const279 OverlayEdge::getEdgeRing() const
280 {
281 return edgeRing;
282 }
283
284 /*public*/
285 const MaximalEdgeRing*
getEdgeRingMax() const286 OverlayEdge::getEdgeRingMax() const
287 {
288 return maxEdgeRing;
289 }
290
291 /*public*/
292 void
setEdgeRingMax(const MaximalEdgeRing * p_maximalEdgeRing)293 OverlayEdge::setEdgeRingMax(const MaximalEdgeRing* p_maximalEdgeRing)
294 {
295 maxEdgeRing = p_maximalEdgeRing;
296 }
297
298 /*public friend*/
299 std::ostream&
operator <<(std::ostream & os,const OverlayEdge & oe)300 operator<<(std::ostream& os, const OverlayEdge& oe)
301 {
302 os << "OE( " << oe.orig();
303 if (oe.pts->size() > 2) {
304 os << ", " << oe.directionPt();
305 }
306 os << " .. " << oe.dest() << " ) ";
307 oe.label->toString(oe.direction, os);
308 os << oe.resultSymbol();
309 os << " / Sym: ";
310 oe.symOE()->getLabel()->toString(oe.symOE()->direction, os);
311 os << oe.symOE()->resultSymbol();
312 return os;
313 }
314
315 /*public*/
316 std::string
resultSymbol() const317 OverlayEdge::resultSymbol() const
318 {
319 if (isInResultArea()) return std::string(" resA");
320 if (isInResultLine()) return std::string(" resL");
321 return std::string("");
322 }
323
324
325
326 } // namespace geos.operation.overlayng
327 } // namespace geos.operation
328 } // namespace geos
329