Stable Tag: Copying everything over
[synfig.git] / ETL / tags / stable / ETL / _angle.h
diff --git a/ETL/tags/stable/ETL/_angle.h b/ETL/tags/stable/ETL/_angle.h
new file mode 100644 (file)
index 0000000..1be01bb
--- /dev/null
@@ -0,0 +1,441 @@
+/* ========================================================================
+** Extended Template and Library
+** Angle Abstraction Class Implementation
+** $Id$
+**
+** Copyright (c) 2002 Robert B. Quattlebaum Jr.
+**
+** 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 <cmath>
+#include <functional>
+
+/* === M A C R O S ========================================================= */
+
+#ifndef PI
+# define PI (3.1415926535897932384626433832795029L)
+# define HALF_PI (PI/2)
+#endif
+
+/* === 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 rotations
+
+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;
+       }
+
+       //! 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=(value_type)std::floor(v+0.5f);
+               return ret;
+       }
+
+       /*! Returns true if the shortest
+               angle between the left-hand and
+               right-hand side is clockwise */
+       bool
+       operator<(const angle &rhs)const
+       { return v<rhs.v; }
+//     { return dist(rhs).v<(value_type)0.0; }
+
+       /*! Returns true if the shortest
+               angle between the left-hand and
+               right-hand side is counter-clockwise */
+       bool
+       operator>(const angle &rhs)const
+       { return v>rhs.v; }
+//     { return dist(rhs).v>(value_type)0.0; }
+
+       /*! Returns true if the shortest
+               angle between the left-hand and
+               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 v<=rhs.v; }
+//     { return dist(rhs).v<=(value_type)0.0; }
+
+       /*! Returns true if the shortest
+               angle between the left-hand and
+               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 v>=rhs.v; }
+//     { 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 v==rhs.v; }
+//     { return dist(rhs).v==(value_type)0.0; }
+
+       /*! Returns false if the angles
+               are refer to the same point
+               on the unit circle. */
+       bool
+       operator!=(const angle &rhs)const
+       { return v!=rhs.v; }
+//     { return dist(rhs).v!=(value_type)0.0; }
+
+       //! 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;
+       }
+
+       static angle
+       zero()
+       {
+               angle ret;
+               ret.v=0;
+               return ret;
+       }
+
+       static angle
+       one()
+       {
+               angle ret;
+               ret.v=PI;
+               return ret;
+       }
+
+       static angle
+       half()
+       {
+               angle ret;
+               ret.v=PI*0.5;
+               return ret;
+       }
+
+       bool operator!()const { return v==0; }
+
+private:
+
+       static value_type rot_floor(value_type x)
+       { return static_cast<value_type>(std::floor(x/(PI*2))*PI*2); }
+
+public:
+       /*
+       ** Converstion Classes
+       */
+
+       class rad;
+       class deg;
+       class rot;
+
+       /*
+       ** Trigometric 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); }
+#ifndef ETL_NO_DEPRECATED
+       operator value_type()const ETL_DEPRECATED_FUNCTION;
+#endif
+       value_type get()const { return v; }
+}; // 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<value_type>(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<value_type>(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); }
+       operator value_type()const ETL_DEPRECATED_FUNCTION;
+#ifndef ETL_NO_DEPRECATED
+       value_type get()const { return (value_type)std::cos(v); }
+#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); }
+#ifndef ETL_NO_DEPRECATED
+       operator value_type()const ETL_DEPRECATED_FUNCTION;
+#endif
+       value_type get()const { return (value_type)std::tan(v); }
+}; // END of class angle::tan
+inline angle::tan::operator angle::value_type()const { return get(); }
+
+_ETL_END_NAMESPACE
+
+//#include <iostream>
+
+template <typename T>
+struct affine_combo<etl::angle, T>
+{
+       typedef T time_type;
+
+       //affine_combo() { std::cerr<<"affine_combo<etl::angle,float>: I was created!"<<std::endl; }
+       //~affine_combo() { std::cerr<<"affine_combo<etl::angle,float>: I was DELETED!"<<std::endl; }
+
+       etl::angle operator()(const etl::angle &a,const etl::angle &b,const time_type &t)const
+       {
+               return b.dist(a)*(float)t+a;
+       }
+
+       etl::angle reverse(const etl::angle &x, const etl::angle &b, const time_type &t)const
+       {
+               return x.dist(b*(float)t)*(float)(time_type(1)/(time_type(1)-t));
+       }
+};
+
+template <>
+struct distance_func<etl::angle> : public std::binary_function<etl::angle, etl::angle, etl::angle>
+{
+       etl::angle operator()(const etl::angle &a,const etl::angle &b)const
+       {
+               etl::angle delta=b.dist(a);
+               //if(delta<etl::angle::zero())
+               //      return delta+etl::angle::one();
+               return delta;
+       }
+
+       etl::angle cook(const etl::angle &x)const { return x; }
+       etl::angle uncook(const etl::angle &x)const { return x; }
+};
+
+
+/* === E N D =============================================================== */
+
+#endif