[geos-commits] r2072 - trunk/source/algorithm
svn_geos at osgeo.org
svn_geos at osgeo.org
Fri Dec 21 15:50:50 EST 2007
Author: benjubb
Date: 2007-12-21 15:50:50 -0500 (Fri, 21 Dec 2007)
New Revision: 2072
Added:
trunk/source/algorithm/RayCrossingCounter.cpp
Log:
Added: trunk/source/algorithm/RayCrossingCounter.cpp
===================================================================
--- trunk/source/algorithm/RayCrossingCounter.cpp (rev 0)
+++ trunk/source/algorithm/RayCrossingCounter.cpp 2007-12-21 20:50:50 UTC (rev 2072)
@@ -0,0 +1,157 @@
+/**********************************************************************
+ * $Id:
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#include <geos/algorithm/RayCrossingCounter.h>
+#include <geos/algorithm/RobustDeterminant.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/Location.h>
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateSequence.h>
+
+
+namespace geos {
+namespace algorithm {
+//
+// private:
+//
+
+//
+// protected:
+//
+
+//
+// public:
+//
+/*static*/ int
+RayCrossingCounter::locatePointInRing( const geom::Coordinate * point, const geom::CoordinateSequence * ring)
+{
+ RayCrossingCounter * rcc = new RayCrossingCounter( point);
+
+ for (int i = 1, ni = ring->size(); i < ni; i++)
+ {
+ const geom::Coordinate & p1 = (*ring)[ i ];
+ const geom::Coordinate & p2 = (*ring)[ i - 1 ];
+
+ rcc->countSegment( &p1, &p2);
+
+ if ( rcc->isOnSegment() )
+ return rcc->getLocation();
+ }
+ return rcc->getLocation();
+}
+
+
+void
+RayCrossingCounter::countSegment( const geom::Coordinate * p1, const geom::Coordinate * p2)
+{
+ // For each segment, check if it crosses
+ // a horizontal ray running from the test point in the positive x direction.
+
+ // check if the segment is strictly to the left of the test point
+ if (p1->x < point->x && p2->x < point->x)
+ return;
+
+ // check if the point is equal to the current ring vertex
+ if (point->x == p2->x && point->y == p2->y)
+ {
+ isPointOnSegment = true;
+ return;
+ }
+
+ // For horizontal segments, check if the point is on the segment.
+ // Otherwise, horizontal segments are not counted.
+ if (p1->y == point->y && p2->y == point->y)
+ {
+ double minx = p1->x;
+ double maxx = p2->x;
+
+ if (minx > maxx)
+ {
+ minx = p2->x;
+ maxx = p1->x;
+ }
+
+ if (point->x >= minx && point->x <= maxx)
+ isPointOnSegment = true;
+
+ return;
+ }
+
+ // Evaluate all non-horizontal segments which cross a horizontal ray to the
+ // right of the test pt. To avoid double-counting shared vertices, we use the
+ // convention that
+ // - an upward edge includes its starting endpoint, and excludes its
+ // final endpoint
+ // - a downward edge excludes its starting endpoint, and includes its
+ // final endpoint
+ if (((p1->y > point->y) && (p2->y <= point->y)) ||
+ ((p2->y > point->y) && (p1->y <= point->y)) )
+ {
+ // translate the segment so that the test point lies on the origin
+ double x1 = p1->x - point->x;
+ double y1 = p1->y - point->y;
+ double x2 = p2->x - point->x;
+ double y2 = p2->y - point->y;
+
+ // The translated segment straddles the x-axis. Compute the sign of the
+ // ordinate of intersection with the x-axis. (y2 != y1, so denominator
+ // will never be 0.0)
+ double xIntSign = RobustDeterminant::signOfDet2x2( x1, y1, x2, y2);
+
+ if (xIntSign == 0.0)
+ {
+ isPointOnSegment = true;
+ return;
+ }
+
+ if (y2 < y1)
+ xIntSign = -xIntSign;
+
+ // The segment crosses the ray if the sign is strictly positive.
+ if (xIntSign > 0.0)
+ crossingCount++;
+ }
+}
+
+
+int
+RayCrossingCounter::getLocation()
+{
+ if (isPointOnSegment)
+ return geom::Location::BOUNDARY;
+
+ // The point is in the interior of the ring if the number of X-crossings is
+ // odd.
+ if ((crossingCount % 2) == 1)
+ return geom::Location::INTERIOR;
+
+ return geom::Location::EXTERIOR;
+}
+
+
+bool
+RayCrossingCounter::isPointInPolygon()
+{
+ return getLocation() != geom::Location::EXTERIOR;
+}
+
+
+} // geos::algorithm
+} // geos
+
+/**********************************************************************
+ * $Log$
+ *
+ **********************************************************************/
Property changes on: trunk/source/algorithm/RayCrossingCounter.cpp
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
More information about the geos-commits
mailing list