1 /**********************************************************************
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
6 * Copyright (C) 2011 Sandro Santilli <strk@keybit.net>
7 * Copyright (C) 2005-2006 Refractions Research Inc.
8 * Copyright (C) 2001-2002 Vivid Solutions Inc.
10 * This is free software; you can redistribute and/or modify it under
11 * the terms of the GNU Lesser General Public Licence as published
12 * by the Free Software Foundation.
13 * See the COPYING file for more information.
15 **********************************************************************
17 * Last port: geomgraph/Edge.java r428 (JTS-1.12+)
19 **********************************************************************/
22 #pragma warning(disable:4355)
29 #include <geos/geomgraph/Edge.h>
30 #include <geos/geomgraph/Position.h>
31 #include <geos/geomgraph/Label.h>
32 #include <geos/geomgraph/index/MonotoneChainEdge.h>
33 #include <geos/algorithm/LineIntersector.h>
34 #include <geos/geom/IntersectionMatrix.h>
35 #include <geos/geom/CoordinateSequence.h>
36 #include <geos/geom/CoordinateArraySequence.h> // FIXME: shouldn't use
37 #include <geos/geom/Coordinate.h>
39 //#define GEOS_DEBUG_INTERSECT 0
44 #if GEOS_DEBUG || GEOS_DEBUG_INTERSECT
49 using namespace geos::geom
;
52 namespace geomgraph
{ // geos.geomgraph
54 using namespace geos::geomgraph::index
;
55 using namespace geos::algorithm
;
58 * Updates an IM from the label for an edge.
59 * Handles edges from both L and A geometrys.
62 Edge::updateIM(const Label
& lbl
, IntersectionMatrix
& im
)
64 im
.setAtLeastIfValid(lbl
.getLocation(0,Position::ON
),
65 lbl
.getLocation(1,Position::ON
),
69 im
.setAtLeastIfValid(lbl
.getLocation(0,Position::LEFT
),
70 lbl
.getLocation(1,Position::LEFT
),
73 im
.setAtLeastIfValid(lbl
.getLocation(0,Position::RIGHT
),
74 lbl
.getLocation(1,Position::RIGHT
),
82 //cerr<<"["<<this<<"] ~Edge()"<<endl;
89 Edge::Edge(CoordinateSequence
* newPts
, const Label
& newLabel
)
91 GraphComponent(newLabel
),
104 Edge::Edge(CoordinateSequence
* newPts
)
120 Edge::getMonotoneChainEdge()
123 if (mce
==NULL
) mce
=new MonotoneChainEdge(this);
130 Edge::isCollapsed() const
133 if (!label
.isArea()) return false;
134 if (getNumPoints()!= 3) return false;
135 if (pts
->getAt(0)==pts
->getAt(2) ) return true;
140 Edge::getCollapsedEdge()
143 CoordinateSequence
*newPts
= new CoordinateArraySequence(2);
144 newPts
->setAt(pts
->getAt(0),0);
145 newPts
->setAt(pts
->getAt(1),1);
146 return new Edge(newPts
, Label::toLineLabel(label
));
151 Edge::addIntersections(LineIntersector
*li
, int segmentIndex
, int geomIndex
)
154 cerr
<<"["<<this<<"] Edge::addIntersections("<<li
->toString()<<", "<<segmentIndex
<<", "<<geomIndex
<<") called"<<endl
;
156 for (int i
=0; i
<li
->getIntersectionNum();i
++) {
157 addIntersection(li
,segmentIndex
,geomIndex
,i
);
165 Edge::addIntersection(LineIntersector
*li
,
166 int segmentIndex
, int geomIndex
, int intIndex
)
169 std::cerr
<< "["<<this<<"] Edge::addIntersection("<<li
->toString()<<", "<<segmentIndex
<<", "<<geomIndex
<<", "<<intIndex
<<") called"<< std::endl
;
171 const Coordinate
& intPt
=li
->getIntersection(intIndex
);
172 unsigned int normalizedSegmentIndex
=segmentIndex
;
173 double dist
=li
->getEdgeDistance(geomIndex
,intIndex
);
175 // normalize the intersection point location
176 unsigned int nextSegIndex
=normalizedSegmentIndex
+1;
177 unsigned int npts
=getNumPoints();
178 if (nextSegIndex
<npts
)
180 const Coordinate
& nextPt
=pts
->getAt(nextSegIndex
);
181 // Normalize segment index if intPt falls on vertex
182 // The check for point equality is 2D only - Z values are ignored
183 if (intPt
.equals2D(nextPt
)) {
184 normalizedSegmentIndex
=nextSegIndex
;
190 * Add the intersection point to edge intersection list.
193 cerr
<<"Edge::addIntersection adding to edge intersection list point "<<intPt
.toString()<<endl
;
195 eiList
.add(intPt
,normalizedSegmentIndex
,dist
);
202 Edge::equals(const Edge
& e
) const
206 unsigned int npts1
=getNumPoints();
207 unsigned int npts2
=e
.getNumPoints();
209 if (npts1
!= npts2
) return false;
211 bool isEqualForward
=true;
212 bool isEqualReverse
=true;
214 for (unsigned int i
=0, iRev
=npts1
-1; i
<npts1
; ++i
, --iRev
)
216 const Coordinate
&e1pi
=pts
->getAt(i
);
217 const Coordinate
&e2pi
=e
.pts
->getAt(i
);
218 const Coordinate
&e2piRev
=e
.pts
->getAt(iRev
);
220 if ( !e1pi
.equals2D(e2pi
) ) isEqualForward
=false;
221 if ( !e1pi
.equals2D(e2piRev
) ) isEqualReverse
=false;
222 if ( !isEqualForward
&& !isEqualReverse
) return false;
229 Edge::isPointwiseEqual(const Edge
*e
) const
234 cerr
<<"Edge::isPointwiseEqual call"<<endl
;
236 unsigned int npts
=getNumPoints();
237 unsigned int enpts
=e
->getNumPoints();
238 if (npts
!=enpts
) return false;
240 cerr
<<"Edge::isPointwiseEqual scanning "<<enpts
<<"x"<<npts
<<" points"<<endl
;
242 for (unsigned int i
=0; i
<npts
; ++i
)
244 if (!pts
->getAt(i
).equals2D(e
->pts
->getAt(i
))) {
256 std::stringstream ss
;
261 // Dunno how to implemente this in terms of operator<<
263 Edge::printReverse() const
270 if ( name
!= "" ) os
<< " name:" << name
;
272 os
<< " label:" << label
273 << " depthDelta:" << depthDelta
276 unsigned int npts
=getNumPoints();
277 for (unsigned int i
=npts
; i
>0; --i
)
279 if (i
<npts
) os
<< ", ";
280 os
<< pts
->getAt(i
-1).toString();
290 // compute envelope lazily
294 unsigned int npts
=getNumPoints();
295 for (unsigned int i
= 0; i
<npts
; ++i
)
297 env
->expandToInclude(pts
->getAt(i
));
305 operator<< (std::ostream
&os
, const Edge
& e
)
308 if ( e
.name
!= "" ) os
<< " " << e
.name
;
314 << " " << e
.depthDelta
320 } // namespace geos.geomgraph