[geos-commits] r2342 - in trunk/source: algorithm headers/geos/algorithm

svn_geos at osgeo.org svn_geos at osgeo.org
Thu Apr 9 12:22:27 EDT 2009


Author: strk
Date: 2009-04-09 12:22:26 -0400 (Thu, 09 Apr 2009)
New Revision: 2342

Added:
   trunk/source/algorithm/Angle.cpp
   trunk/source/headers/geos/algorithm/Angle.h
Modified:
   trunk/source/algorithm/Makefile.am
   trunk/source/headers/geos/algorithm/Makefile.am
Log:
Port algorithm.Angle from JTS-1.9


Added: trunk/source/algorithm/Angle.cpp
===================================================================
--- trunk/source/algorithm/Angle.cpp	                        (rev 0)
+++ trunk/source/algorithm/Angle.cpp	2009-04-09 16:22:26 UTC (rev 2342)
@@ -0,0 +1,206 @@
+/**********************************************************************
+ * $Id$
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2009  Sandro Santilli <strk at keybit.net>
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: algorithm/Angle.java rev. 1.6 (JTS-1.9)
+ *
+ **********************************************************************/
+
+#include <cmath> 
+
+#include <geos/algorithm/Angle.h>
+#include <geos/algorithm/CGAlgorithms.h>
+#include <geos/geom/Coordinate.h>
+
+namespace geos {
+namespace algorithm { // geos.algorithm
+
+namespace { 
+	const double PI = 3.14159265358979;
+}
+
+const double Angle::PI_TIMES_2 = 2.0 * PI; 
+const double Angle::PI_OVER_2 = PI / 2.0;
+const double Angle::PI_OVER_4 = PI / 4.0;
+
+/* public static */
+double
+Angle::toDegrees(double radians)
+{
+      return (radians * 180) / (PI);
+}
+
+/* public static */
+double
+Angle::toRadians(double angleDegrees)
+{
+	return (angleDegrees * PI) / 180.0;
+}
+
+/* public static */
+double
+Angle::angle(const geom::Coordinate& p0,
+             const geom::Coordinate& p1)
+{
+      double dx = p1.x - p0.x;
+      double dy = p1.y - p0.y;
+      return atan2(dy, dx);
+}
+
+/* public static */
+double
+Angle::angle(const geom::Coordinate& p)
+{
+	return atan2(p.y, p.x);
+}
+
+/* public static */
+bool
+Angle::isAcute(const geom::Coordinate& p0,
+               const geom::Coordinate& p1,
+               const geom::Coordinate& p2)
+{
+	// relies on fact that A dot B is positive iff A ang B is acute
+	double dx0 = p0.x - p1.x;
+	double dy0 = p0.y - p1.y;
+	double dx1 = p2.x - p1.x;
+	double dy1 = p2.y - p1.y;
+	double dotprod = dx0 * dx1 + dy0 * dy1;
+	return dotprod > 0;
+}
+
+/* public static */
+bool
+Angle::isObtuse(const geom::Coordinate& p0,
+                const geom::Coordinate& p1,
+                const geom::Coordinate& p2)
+{
+	// relies on fact that A dot B is negative iff A ang B is obtuse
+	double dx0 = p0.x - p1.x;
+	double dy0 = p0.y - p1.y;
+	double dx1 = p2.x - p1.x;
+	double dy1 = p2.y - p1.y;
+	double dotprod = dx0 * dx1 + dy0 * dy1;
+	return dotprod < 0;
+}
+
+/* public static */
+double
+Angle::angleBetween(const geom::Coordinate& tip1,
+                    const geom::Coordinate& tail,
+                    const geom::Coordinate& tip2)
+{
+	double a1 = angle(tail, tip1);
+	double a2 = angle(tail, tip2);
+
+	return diff(a1, a2);
+}
+
+/* public static */
+double
+Angle::angleBetweenOriented(const geom::Coordinate& tip1,
+                            const geom::Coordinate& tail,
+                            const geom::Coordinate& tip2)
+{
+	double a1 = angle(tail, tip1);
+	double a2 = angle(tail, tip2);
+	double angDel = a2 - a1;
+
+	// normalize, maintaining orientation
+	if (angDel <= -PI)
+		return angDel + PI_TIMES_2;
+	if (angDel > PI)
+		return angDel - PI_TIMES_2;
+	return angDel;
+}
+
+/* public static */
+double
+Angle::interiorAngle(const geom::Coordinate& p0, const geom::Coordinate& p1,
+                     const geom::Coordinate& p2)
+{
+	double anglePrev = angle(p1, p0);
+	double angleNext = angle(p1, p2);
+	return fabs(angleNext - anglePrev);
+}
+
+/* public static */
+int
+Angle::getTurn(double ang1, double ang2)
+{
+	double crossproduct = sin(ang2 - ang1);
+
+	if (crossproduct > 0) {
+		return COUNTERCLOCKWISE;
+	}
+	if (crossproduct < 0) {
+		return CLOCKWISE;
+	}
+	return NONE;
+}
+
+/* public static */
+double
+Angle::normalize(double angle)
+{
+	while (angle > PI)
+		angle -= PI_TIMES_2;
+	while (angle <= -PI)
+		angle += PI_TIMES_2;
+	return angle;
+}
+
+/* public static */
+double
+Angle::normalizePositive(double angle)
+{
+	if (angle < 0.0) {
+		while (angle < 0.0)
+			angle += PI_TIMES_2;
+		// in case round-off error bumps the value over
+		if (angle >= PI_TIMES_2)
+			angle = 0.0;
+	}
+	else {
+		while (angle >= PI_TIMES_2)
+			angle -= PI_TIMES_2;
+		// in case round-off error bumps the value under
+		if (angle < 0.0)
+			angle = 0.0;
+	}
+	return angle;
+}
+
+/* public static */
+double
+Angle::diff(double ang1, double ang2)
+{
+	double delAngle;
+
+	if (ang1 < ang2) {
+		delAngle = ang2 - ang1;
+	} else {
+		delAngle = ang1 - ang2;
+	}
+
+	if (delAngle > PI) {
+		delAngle = (2 * PI) - delAngle;
+	}
+
+	return delAngle;
+}
+
+} // namespace geos.algorithm
+} //namespace geos
+

Modified: trunk/source/algorithm/Makefile.am
===================================================================
--- trunk/source/algorithm/Makefile.am	2009-04-09 11:45:57 UTC (rev 2341)
+++ trunk/source/algorithm/Makefile.am	2009-04-09 16:22:26 UTC (rev 2342)
@@ -6,6 +6,7 @@
 INCLUDES = -I$(top_srcdir)/source/headers 
 
 libalgorithm_la_SOURCES = \
+	Angle.cpp \
 	CentroidArea.cpp \
 	CentroidLine.cpp \
 	CentroidPoint.cpp \

Added: trunk/source/headers/geos/algorithm/Angle.h
===================================================================
--- trunk/source/headers/geos/algorithm/Angle.h	                        (rev 0)
+++ trunk/source/headers/geos/algorithm/Angle.h	2009-04-09 16:22:26 UTC (rev 2342)
@@ -0,0 +1,228 @@
+/**********************************************************************
+ * $Id$
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2009  Sandro Santilli <strk at keybit.net>
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: algorithm/Angle.java rev. 1.6 (JTS-1.9)
+ *
+ **********************************************************************/
+
+#ifndef GEOS_ALGORITHM_ANGLE_H
+#define GEOS_ALGORITHM_ANGLE_H
+
+#include <geos/algorithm/CGAlgorithms.h> // for constants
+
+// Forward declarations
+namespace geos {
+	namespace geom {
+		class Coordinate;
+	}
+}
+
+namespace geos {
+namespace algorithm { // geos::algorithm
+
+/// Utility functions for working with angles.
+//
+/// Unless otherwise noted, methods in this class express angles in radians.
+///
+class Angle
+{
+public:
+
+	static const double PI_TIMES_2; // 2.0 * PI;
+	static const double PI_OVER_2; // PI / 2.0;
+	static const double PI_OVER_4; // PI / 4.0;
+
+	/// Constant representing counterclockwise orientation
+	static const int COUNTERCLOCKWISE = CGAlgorithms::COUNTERCLOCKWISE;
+
+	/// Constant representing clockwise orientation 
+	static const int CLOCKWISE = CGAlgorithms::CLOCKWISE;
+
+	/// Constant representing no orientation 
+	static const int NONE = CGAlgorithms::COLLINEAR;
+
+	/// Converts from radians to degrees.
+	//
+	/// @param radians an angle in radians
+	/// @return the angle in degrees
+	///
+	static double toDegrees(double radians);
+
+	/// Converts from degrees to radians.
+	//
+	/// @param angleDegrees an angle in degrees
+	/// @return the angle in radians
+	///
+	static double toRadians(double angleDegrees);
+
+	/// \brief
+	/// Returns the angle of the vector from p0 to p1,
+	/// relative to the positive X-axis.
+	//
+	/// The angle is normalized to be in the range [ -Pi, Pi ].
+	///
+	/// @return the normalized angle (in radians) that p0-p1 makes
+	///         with the positive x-axis.
+	///
+	static double angle(const geom::Coordinate& p0,
+	                    const geom::Coordinate& p1);
+
+	/// \brief
+	/// Returns the angle that the vector from (0,0) to p,
+	/// relative to the positive X-axis.
+	//
+	/// The angle is normalized to be in the range ( -Pi, Pi ].
+	///
+	/// @return the normalized angle (in radians) that p makes
+	///          with the positive x-axis.
+	///
+	static double angle(const geom::Coordinate& p);
+
+	/// Tests whether the angle between p0-p1-p2 is acute.
+	//
+	/// An angle is acute if it is less than 90 degrees.
+	/// 
+	/// Note: this implementation is not precise (determistic) for
+	///       angles very close to 90 degrees.
+	///
+	/// @param p0 an endpoint of the angle
+	/// @param p1 the base of the angle
+	/// @param p2 the other endpoint of the angle
+	///
+	static bool isAcute(const geom::Coordinate& p0,
+	                    const geom::Coordinate& p1,
+	                    const geom::Coordinate& p2);
+
+	/// Tests whether the angle between p0-p1-p2 is obtuse.
+	//
+	/// An angle is obtuse if it is greater than 90 degrees.
+	/// 
+	/// Note: this implementation is not precise (determistic) for
+	///       angles very close to 90 degrees.
+	///
+	/// @param p0 an endpoint of the angle
+	/// @param p1 the base of the angle
+	/// @param p2 the other endpoint of the angle
+	///
+	static bool isObtuse(const geom::Coordinate& p0,
+	                     const geom::Coordinate& p1,
+	                     const geom::Coordinate& p2);
+
+	/// Returns the unoriented smallest angle between two vectors.
+	//
+	/// The computed angle will be in the range [0, Pi).
+	///
+	/// @param tip1 the tip of one vector
+	/// @param tail the tail of each vector
+	/// @param tip2 the tip of the other vector
+	/// @return the angle between tail-tip1 and tail-tip2
+	///
+	static double angleBetween(const geom::Coordinate& tip1,
+	                           const geom::Coordinate& tail,
+	                           const geom::Coordinate& tip2);
+
+	/// Returns the oriented smallest angle between two vectors.
+	//
+	/// The computed angle will be in the range (-Pi, Pi].
+	/// A positive result corresponds to a counterclockwise rotation
+	/// from v1 to v2;
+	/// a negative result corresponds to a clockwise rotation.
+	///
+	/// @param tip1 the tip of v1
+	/// @param tail the tail of each vector
+	/// @param tip2 the tip of v2
+	/// @return the angle between v1 and v2, relative to v1
+	///
+	static double angleBetweenOriented(const geom::Coordinate& tip1,
+	                                   const geom::Coordinate& tail,
+	                                   const geom::Coordinate& tip2);
+
+	/// Computes the interior angle between two segments of a ring.
+	//
+	/// The ring is assumed to be oriented in a clockwise direction.
+	/// The computed angle will be in the range [0, 2Pi]
+	///
+	/// @param p0
+	///          a point of the ring
+	/// @param p1
+	///          the next point of the ring
+	/// @param p2
+	///          the next point of the ring
+	/// @return the interior angle based at <code>p1</code>
+	///
+	static double interiorAngle(const geom::Coordinate& p0,
+	                            const geom::Coordinate& p1,
+	                            const geom::Coordinate& p2);
+
+	/// \brief
+	/// Returns whether an angle must turn clockwise or counterclockwise
+	/// to overlap another angle.
+	///
+	/// @param ang1 an angle (in radians)
+	/// @param ang2 an angle (in radians)
+	/// @return whether a1 must turn CLOCKWISE, COUNTERCLOCKWISE or
+	///         NONE to overlap a2.
+	///
+	static int getTurn(double ang1, double ang2);
+
+	/// \brief
+	/// Computes the normalized value of an angle, which is the
+	/// equivalent angle in the range ( -Pi, Pi ].
+	///
+	/// @param angle the angle to normalize
+	/// @return an equivalent angle in the range (-Pi, Pi]
+	///
+	static double normalize(double angle);
+
+	/// \brief
+	/// Computes the normalized positive value of an angle,
+	/// which is the equivalent angle in the range [ 0, 2*Pi ).
+	///
+	/// E.g.:
+	/// - normalizePositive(0.0) = 0.0
+	/// - normalizePositive(-PI) = PI
+	/// - normalizePositive(-2PI) = 0.0
+	/// - normalizePositive(-3PI) = PI
+	/// - normalizePositive(-4PI) = 0
+	/// - normalizePositive(PI) = PI
+	/// - normalizePositive(2PI) = 0.0
+	/// - normalizePositive(3PI) = PI
+	/// - normalizePositive(4PI) = 0.0
+	///
+	/// @param angle the angle to normalize, in radians
+	/// @return an equivalent positive angle
+	///
+	static double normalizePositive(double angle);
+
+
+	/// Computes the unoriented smallest difference between two angles.
+	//
+	/// The angles are assumed to be normalized to the range [-Pi, Pi].
+	/// The result will be in the range [0, Pi].
+	///
+	/// @param ang1 the angle of one vector (in [-Pi, Pi] )
+	/// @param ang2 the angle of the other vector (in range [-Pi, Pi] )
+	/// @return the angle (in radians) between the two vectors
+	///         (in range [0, Pi] )
+	///
+	static double diff(double ang1, double ang2);
+};
+
+
+} // namespace geos::algorithm
+} // namespace geos
+
+
+#endif // GEOS_ALGORITHM_ANGLE_H

Modified: trunk/source/headers/geos/algorithm/Makefile.am
===================================================================
--- trunk/source/headers/geos/algorithm/Makefile.am	2009-04-09 11:45:57 UTC (rev 2341)
+++ trunk/source/headers/geos/algorithm/Makefile.am	2009-04-09 16:22:26 UTC (rev 2342)
@@ -19,6 +19,7 @@
 	PointLocator.h	
 
 noinst_HEADERS = 			\
+	Angle.h				\
 	CGAlgorithms.h			\
 	CentralEndpointIntersector.h	\
 	CentroidArea.h			\



More information about the geos-commits mailing list