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