/* ======================================================================== ** Extended Template and Library ** Angle Abstraction Class Implementation ** $Id$ ** ** Copyright (c) 2002 Robert B. Quattlebaum Jr. ** Copyright (c) 2007 Chris Moore ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as ** published by the Free Software Foundation; either version 2 of ** the License, or (at your option) any later version. ** ** This package is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** ** === N O T E S =========================================================== ** ** This is an internal header file, included by other ETL headers. ** You should not attempt to use it directly. ** ** ========================================================================= */ /* === S T A R T =========================================================== */ #ifndef __ETL__ANGLE_H #define __ETL__ANGLE_H /* === H E A D E R S ======================================================= */ #include #include #include /* === M A C R O S ========================================================= */ #ifndef PI # define PI (3.1415926535897932384626433832795029L) # define HALF_PI (PI/2) #endif #define ANGLE_EPSILON (1.0e-6) /* === T Y P E D E F S ===================================================== */ /* === C L A S S E S & S T R U C T S ======================================= */ _ETL_BEGIN_NAMESPACE // ======================================================================== /*! \class angle _angle.h ETL/angle ** \brief Abstraction of the concept of an angle ** \see angle::deg, angle::rad, angle::rot, angle::sin, angle::cos, angle::tan, fastangle ** \writeme */ class angle { public: typedef float value_type; protected: typedef value_type unit; unit v; //! Stored in radians; positive values indicate counter-clockwise. public: /* ** Arithmetic Operators */ const angle & operator+=(const angle &rhs) { v+=rhs.v; return *this; } const angle & operator-=(const angle &rhs) { v-=rhs.v; return *this; } const angle & operator*=(const unit &rhs) { v*=rhs; return *this; } const angle & operator/=(const unit &rhs) { v/=rhs; return *this; } //! Angle Addition Operator angle operator+(const angle &rhs)const { return angle(*this)+=rhs; } //! Angle Subtraction Operator /*! \sa angle dist(const angle &) */ angle operator-(const angle &rhs)const { return angle(*this)-=rhs; } //! Angle Scalar Multiplication Operator /*! This operator will multiply the given angle by the given scalar value. */ angle operator*(const unit &rhs)const { return angle(*this)*=rhs; } angle operator/(const unit &rhs)const { return angle(*this)/=rhs; } //! Angle Negation angle operator-()const { angle ret; ret.v=-v; return ret; } #ifdef ETL_NOT_USED //! 180 degree rotation operator /*! Returns the angle directly opposite of the given angle, and will yield a result between 0 and 2PI */ angle operator~()const { angle ret; ret.v = v+PI; return ret.mod(); } #endif // ETL_NOT_USED #ifdef ETL_WRAP_ANGLES /*! Returns true if the shortest angle from the left-hand to the right-hand side is counter-clockwise */ bool operator<(const angle &rhs)const { return dist(rhs).v<(value_type)0.0; } /*! Returns true if the shortest angle from the left-hand to the right-hand side is clockwise */ bool operator>(const angle &rhs)const { return dist(rhs).v>(value_type)0.0; } /*! Returns true if the shortest angle from the left-hand to the right-hand side is counter-clockwise, or if the angles are refer to the same point on the unit circle. */ bool operator<=(const angle &rhs)const { return dist(rhs).v<=(value_type)0.0; } /*! Returns true if the shortest angle from the left-hand to the right-hand side is clockwise, or if the angles are refer to the same point on the unit circle. */ bool operator>=(const angle &rhs)const { return dist(rhs).v>=(value_type)0.0; } /*! Returns true if the angles are refer to the same point on the unit circle. */ bool operator==(const angle &rhs)const { return std::abs(dist(rhs).v)ANGLE_EPSILON; } #else // ETL_WRAP_ANGLES /*! Returns true if the left-hand side is less than the right-hand side */ bool operator<(const angle &rhs)const { return v < rhs.v; } /*! Returns true if the left-hand side is greater than the right-hand side */ bool operator>(const angle &rhs)const { return v > rhs.v; } /*! Returns true if the left-hand side is less or equal to the right-hand side */ bool operator<=(const angle &rhs)const { return v <= rhs.v; } /*! Returns true if the left-hand side is greater than or equal to the right-hand side */ bool operator>=(const angle &rhs)const { return v >= rhs.v; } /*! Returns true if the angles are the same, or close */ bool operator==(const angle &rhs)const { return std::abs(v - rhs.v)ANGLE_EPSILON; } #endif // ETL_WRAP_ANGLES //! Absolute Angle Function /*! This function will return the absolute value of the angle. */ angle abs()const { angle ret; ret.v=std::abs(v); return ret; } #ifdef ETL_WRAP_ANGLES //! Angle Difference Function /*! This function will return the shortest physical distance between two angles, from -PI/2 to PI/2 \sa angle operator-(const angle &) */ angle dist(const angle &rhs)const { angle ret; ret.v=v-rhs.v; ret.v-=rot_floor(ret.v+PI); return ret; } //! Rotation Modulus /*! This function will return the value of the angle between 0 and 2PI */ angle mod()const { angle ret(*this); ret.v-=rot_floor(ret.v); return ret; } #else // ETL_WRAP_ANGLES //! Angle Difference Function /*! This function will return the difference between two angles, just like \sa angle operator-(const angle &) */ angle dist(const angle &rhs)const { return angle(*this)-=rhs; } //! Rotation Modulus /*! This function will return the value of the angle */ angle mod()const { angle ret(*this); return ret; } #endif // ETL_WRAP_ANGLES //! Zero Rotation (0 degrees) static angle zero() { angle ret; ret.v=0; return ret; } //! One Complete Rotation (360 degrees) static angle one() { angle ret; ret.v=PI*2; return ret; } //! One Half Rotation (180 degrees) static angle half() { angle ret; ret.v=PI; return ret; } bool operator!()const { return std::abs(mod().v) < ANGLE_EPSILON; } private: #ifdef ETL_WRAP_ANGLES static value_type rot_floor(value_type x) { return static_cast(std::floor(x/(PI*2))*PI*2); } #endif // ETL_WRAP_ANGLES public: /* ** Conversion Classes */ class rad; class deg; class rot; /* ** Trigonometric Classes */ class sin; class cos; class tan; /* ** Friend classes */ friend class rad; friend class deg; friend class rot; friend class sin; friend class cos; friend class tan; /* ** Deprecated */ #ifndef ETL_NO_DEPRECATED typedef rad radians; typedef deg degrees; typedef rot rotations; #endif }; // END of class angle // ======================================================================== /*! \class angle::rad _angle.h ETL/angle ** \brief Angle representation in radians ** \see angle ** \writeme */ class angle::rad : public angle { public: explicit rad(const value_type &x) { v=x; } rad(const angle &a):angle(a) { } rad mod()const { return angle::mod(); } rad dist(const angle &rhs)const { return angle::dist(rhs); } value_type get()const { return v; } #ifndef ETL_NO_DEPRECATED // operator value_type()const ETL_DEPRECATED_FUNCTION; #endif }; // END of class angle::radians // inline angle::rad::operator angle::value_type()const { return get(); } // ======================================================================== /*! \class angle::deg _angle.h ETL/angle ** \brief Angle representation in degrees ** \see angle ** \writeme */ class angle::deg : public angle { public: explicit deg(const value_type &x) { v=x*((PI*2)/360); } deg(const angle &a):angle(a) { } deg mod()const { return angle::mod(); } deg dist(const angle &rhs)const { return angle::dist(rhs); } value_type get()const { return v*360/(PI*2); } #ifndef ETL_NO_DEPRECATED // operator value_type()const ETL_DEPRECATED_FUNCTION; #endif }; // END of class angle::degrees // inline angle::deg::operator angle::value_type()const { return get(); } // ======================================================================== /*! \class angle::rot _angle.h ETL/angle ** \brief Angle representation in rotations ** \see angle ** \writeme */ class angle::rot : public angle { public: explicit rot(const value_type &x) { v=x*(PI*2); } rot(const angle &a):angle(a) { } rot mod()const { return angle::mod(); } rot dist(const angle &rhs)const { return angle::dist(rhs); } value_type get()const { return v/(PI*2); } #ifndef ETL_NO_DEPRECATED // operator value_type()const ETL_DEPRECATED_FUNCTION; #endif }; // END of class angle::rotations // inline angle::rot::operator angle::value_type()const { return get(); } // ======================================================================== /*! \class angle::sin _angle.h ETL/angle ** \brief Angle representation as a sine function ** \see angle ** \writeme */ class angle::sin : public angle { public: explicit sin(const value_type &x) { v=static_cast(std::asin(x)); } sin(const angle &a):angle(a) { } sin mod()const { return angle::mod(); } sin dist(const angle &rhs)const { return angle::dist(rhs); } value_type get()const { return static_cast(std::sin(v)); } #ifndef ETL_NO_DEPRECATED // operator value_type()const ETL_DEPRECATED_FUNCTION; #endif }; // END of class angle::sin // inline angle::sin::operator angle::value_type()const { return get(); } // ======================================================================== /*! \class angle::cos _angle.h ETL/angle ** \brief Angle representation as a cosine function ** \see angle ** \writeme */ class angle::cos : public angle { public: explicit cos(const value_type &x) { v=(value_type)(std::acos(x)); } cos(const angle &a):angle(a) { } cos mod()const { return angle::mod(); } cos dist(const angle &rhs)const { return angle::dist(rhs); } value_type get()const { return (value_type)std::cos(v); } #ifndef ETL_NO_DEPRECATED // operator value_type()const ETL_DEPRECATED_FUNCTION; #endif }; // END of class angle::cos // inline angle::cos::operator angle::value_type()const { return get(); } // ======================================================================== /*! \class angle::tan _angle.h ETL/angle ** \brief Angle representation as a tangent function ** \see angle ** \writeme */ class angle::tan : public angle { public: explicit tan(const value_type &x) { v=(value_type)(std::atan(x)); } tan(const value_type &y,const value_type &x) { v=(value_type)(std::atan2(y,x)); } tan(const angle &a):angle(a) { } tan mod()const { return angle::mod(); } tan dist(const angle &rhs)const { return angle::dist(rhs); } value_type get()const { return (value_type)std::tan(v); } #ifndef ETL_NO_DEPRECATED // operator value_type()const ETL_DEPRECATED_FUNCTION; #endif }; // END of class angle::tan // inline angle::tan::operator angle::value_type()const { return get(); } _ETL_END_NAMESPACE //#include template struct affine_combo { typedef T time_type; //affine_combo() { std::cerr<<"affine_combo: I was created!"<: I was DELETED!"< struct distance_func : public std::binary_function { etl::angle operator()(const etl::angle &a,const etl::angle &b)const { etl::angle delta=b.dist(a); //if(delta