From: Mikko Rasa Date: Fri, 17 May 2013 11:12:38 +0000 (+0300) Subject: Improvements to the Angle class X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=29465bb366457a0087f2391cbb30ab04171fa1ff;p=libs%2Fmath.git Improvements to the Angle class Add comparison operators and wrapping functions. Use turn instead of circle in the factory functions and provide an interface to and from turns. --- diff --git a/source/geometry/angle.h b/source/geometry/angle.h index edd7521..2cfb117 100644 --- a/source/geometry/angle.h +++ b/source/geometry/angle.h @@ -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 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 - Angle(const Angle &); + Angle(const Angle &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 -inline Angle::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(const Angle &other) const { return value>other.value; } + bool operator>=(const Angle &other) const { return value>=other.value; } -template -template -inline Angle::Angle(const Angle &other): - value(other.value) -{ } + Angle &wrap_with_base(const Angle &); + Angle &wrap_positive(); + Angle &wrap_balanced(); +}; template inline Angle Angle::from_degrees(T d) @@ -64,45 +67,9 @@ inline Angle Angle::from_radians(T r) } template -inline Angle Angle::right() +inline Angle Angle::from_turns(T t) { - return from_radians(M_PI/2); -} - -template -inline Angle Angle::quarter_circle() -{ - return right(); -} - -template -inline Angle Angle::straight() -{ - return from_radians(M_PI); -} - -template -inline Angle Angle::half_circle() -{ - return straight(); -} - -template -inline Angle Angle::full_circle() -{ - return from_radians(M_PI*2); -} - -template -inline T Angle::degrees() const -{ - return value*180/M_PI; -} - -template -inline T Angle::radians() const -{ - return value; + return Angle(t*2*M_PI); } template @@ -133,6 +100,12 @@ inline Angle operator-(const Angle &a1, const Angle &a2) return r -= a2; } +template +inline Angle operator-(const Angle &a) +{ + return Angle::zero()-a; +} + template inline Angle &Angle::operator*=(T s) { @@ -173,6 +146,61 @@ inline Angle operator/(T s, const Angle &a) return a/s; } +template +inline T operator/(const Angle &a1, const Angle &a2) +{ + return a1.radians()/a2.radians(); +} + +template +inline Angle &Angle::wrap_with_base(const Angle &b) +{ + while(value=b.value+2*M_PI) + value -= 2*M_PI; + return *this; +} + +template +inline Angle &Angle::wrap_positive() +{ + return wrap_with_base(zero()); +} + +template +inline Angle &Angle::wrap_balanced() +{ + return wrap_with_base(-half_turn()); +} + +template +inline Angle wrap_with_base(const Angle &a, const Angle &b) +{ + Angle r = a; + return r.wrap_with_base(b); +} + +template +inline Angle wrap_positive(const Angle &a) +{ + Angle r = a; + return r.wrap_positive(); +} + +template +inline Angle wrap_balanced(const Angle &a) +{ + Angle r = a; + return r.wrap_balanced(); +} + +template +inline Angle abs(const Angle &angle) +{ + return Angle::from_radians(std::abs(angle.radians())); +} + template inline T sin(const Angle &angle) {