]> git.tdb.fi Git - libs/math.git/commitdiff
Improvements to the Angle class
authorMikko Rasa <tdb@tdb.fi>
Fri, 17 May 2013 11:12:38 +0000 (14:12 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 17 May 2013 11:12:38 +0000 (14:12 +0300)
Add comparison operators and wrapping functions.

Use turn instead of circle in the factory functions and provide an
interface to and from turns.

source/geometry/angle.h

index edd752122f3436055028f6dab93332f3836a0f96..2cfb1176005206c870efbf6cefd87170a938afde 100644 (file)
@@ -8,8 +8,7 @@ namespace Geometry {
 
 /**
 A planar angle.  Creating an Angle from a raw value or extracting it requires
-specifying whether degrees or radians are used.  This eliminates a common
-source of errors.
+specifying the units used.  This eliminates a common source of errors.
 */
 template<typename T>
 class Angle
@@ -17,39 +16,43 @@ class Angle
 private:
        T value;
 
-       explicit Angle(T);
+       explicit Angle(T v): value(v) { }
 public:
+       Angle(): value(0) { }
        template<typename U>
-       Angle(const Angle<U> &);
+       Angle(const Angle<U> &other): value(other.value) { }
 
        static Angle from_degrees(T);
        static Angle from_radians(T);
+       static Angle from_turns(T);
 
-       static Angle right();
-       static Angle quarter_circle();
-       static Angle straight();
-       static Angle half_circle();
-       static Angle full_circle();
+       static Angle zero() { return from_radians(0); }
+       static Angle right() { return from_radians(M_PI/2); }
+       static Angle quarter_turn() { return right(); }
+       static Angle straight() { return from_radians(M_PI); }
+       static Angle half_turn() { return straight(); }
+       static Angle full_turn() { return from_radians(2*M_PI); }
 
-       T degrees() const;
-       T radians() const;
+       T degrees() const { return value*180/M_PI; }
+       T radians() const { return value; }
+       T turns() const { return value/(2*M_PI); }
 
        Angle &operator+=(const Angle &);
        Angle &operator-=(const Angle &);
        Angle &operator*=(T);
        Angle &operator/=(T);
-};
 
-template<typename T>
-inline Angle<T>::Angle(T v):
-       value(v)
-{ }
+       bool operator==(const Angle &other) const { return value==other.value; }
+       bool operator!=(const Angle &other) const { return value!=other.value; }
+       bool operator<(const Angle &other) const { return value<other.value; }
+       bool operator<=(const Angle &other) const { return value<=other.value; }
+       bool operator>(const Angle &other) const { return value>other.value; }
+       bool operator>=(const Angle &other) const { return value>=other.value; }
 
-template<typename T>
-template<typename U>
-inline Angle<T>::Angle(const Angle<U> &other):
-       value(other.value)
-{ }
+       Angle &wrap_with_base(const Angle &);
+       Angle &wrap_positive();
+       Angle &wrap_balanced();
+};
 
 template<typename T>
 inline Angle<T> Angle<T>::from_degrees(T d)
@@ -64,45 +67,9 @@ inline Angle<T> Angle<T>::from_radians(T r)
 }
 
 template<typename T>
-inline Angle<T> Angle<T>::right()
+inline Angle<T> Angle<T>::from_turns(T t)
 {
-       return from_radians(M_PI/2);
-}
-
-template<typename T>
-inline Angle<T> Angle<T>::quarter_circle()
-{
-       return right();
-}
-
-template<typename T>
-inline Angle<T> Angle<T>::straight()
-{
-       return from_radians(M_PI);
-}
-
-template<typename T>
-inline Angle<T> Angle<T>::half_circle()
-{
-       return straight();
-}
-
-template<typename T>
-inline Angle<T> Angle<T>::full_circle()
-{
-       return from_radians(M_PI*2);
-}
-
-template<typename T>
-inline T Angle<T>::degrees() const
-{
-       return value*180/M_PI;
-}
-
-template<typename T>
-inline T Angle<T>::radians() const
-{
-       return value;
+       return Angle<T>(t*2*M_PI);
 }
 
 template<typename T>
@@ -133,6 +100,12 @@ inline Angle<T> operator-(const Angle<T> &a1, const Angle<T> &a2)
        return r -= a2;
 }
 
+template<typename T>
+inline Angle<T> operator-(const Angle<T> &a)
+{
+       return Angle<T>::zero()-a;
+}
+
 template<typename T>
 inline Angle<T> &Angle<T>::operator*=(T s)
 {
@@ -173,6 +146,61 @@ inline Angle<T> operator/(T s, const Angle<T> &a)
        return a/s;
 }
 
+template<typename T>
+inline T operator/(const Angle<T> &a1, const Angle<T> &a2)
+{
+       return a1.radians()/a2.radians();
+}
+
+template<typename T>
+inline Angle<T> &Angle<T>::wrap_with_base(const Angle<T> &b)
+{
+       while(value<b.value)
+               value += 2*M_PI;
+       while(value>=b.value+2*M_PI)
+               value -= 2*M_PI;
+       return *this;
+}
+
+template<typename T>
+inline Angle<T> &Angle<T>::wrap_positive()
+{
+       return wrap_with_base(zero());
+}
+
+template<typename T>
+inline Angle<T> &Angle<T>::wrap_balanced()
+{
+       return wrap_with_base(-half_turn());
+}
+
+template<typename T>
+inline Angle<T> wrap_with_base(const Angle<T> &a, const Angle<T> &b)
+{
+       Angle<T> r = a;
+       return r.wrap_with_base(b);
+}
+
+template<typename T>
+inline Angle<T> wrap_positive(const Angle<T> &a)
+{
+       Angle<T> r = a;
+       return r.wrap_positive();
+}
+
+template<typename T>
+inline Angle<T> wrap_balanced(const Angle<T> &a)
+{
+       Angle<T> r = a;
+       return r.wrap_balanced();
+}
+
+template<typename T>
+inline Angle<T> abs(const Angle<T> &angle)
+{
+       return Angle<T>::from_radians(std::abs(angle.radians()));
+}
+
 template<typename T>
 inline T sin(const Angle<T> &angle)
 {