angle.h

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 // $Id: angle.h,v 1.48.18.1 2007/03/25 21:23:44 oliver Exp $
00005 //
00006 
00007 #ifndef BALL_MATHS_ANGLE_H
00008 #define BALL_MATHS_ANGLE_H
00009 
00010 #ifndef BALL_COMMON_EXCEPTION_H
00011 # include <BALL/COMMON/exception.h>
00012 #endif
00013 
00014 #ifndef BALL_COMMON_DEBUG_H
00015 # include <BALL/COMMON/debug.h>
00016 #endif
00017 
00018 #ifndef BALL_COMMON_CREATE_H
00019 # include <BALL/COMMON/create.h>
00020 #endif
00021 
00022 #ifndef BALL_MATHS_COMMON_H
00023 # include <BALL/MATHS/common.h>
00024 #endif
00025 
00026 namespace BALL 
00027 {
00033   template <typename T>
00034   class TAngle;
00035 
00036   template <typename T>
00037   BALL_INLINE
00038   TAngle<T> operator * (const T& val, const TAngle<T>& angle);
00039 
00040   template <typename T>
00041   BALL_INLINE
00042   TAngle<T> operator + (const T& val, const TAngle<T>& angle);
00043 
00044   template <typename T>
00045   BALL_INLINE
00046   TAngle<T> operator - (const T& val, const TAngle<T>& angle);
00047 
00053   template <typename T>
00054   class TAngle
00055   {
00056     public:
00057 
00058     BALL_CREATE(TAngle<T>)
00059 
00060     
00063 
00069     enum Range
00070     {
00071       // no limitations
00072       RANGE__UNLIMITED = 0, 
00073       // 0 <= angle <= 360, 0 <= angle <= (Constants::PI * 2)
00074       RANGE__UNSIGNED  = 1, 
00075       // -180 <= angle <= 180, -Constants::PI <= angle <= Constants::PI
00076       RANGE__SIGNED    = 2 
00077     };
00079 
00082 
00086     TAngle();
00087 
00093     TAngle(const TAngle& angle);
00094 
00102     explicit TAngle(const T& new_value, bool radian = true);
00103 
00106     virtual ~TAngle()
00107     {
00108     }
00109 
00113     virtual void clear()
00114     {
00115       value = (T)0;
00116     }
00118 
00122 
00125     void swap(TAngle& angle);
00126 
00133     void set(const T& new_value, bool radian = true);
00134 
00138     void set(const TAngle& angle);
00139 
00142     TAngle& operator = (const TAngle& angle);
00143 
00149     TAngle& operator = (const T& new_value);
00150 
00154     void get(TAngle& angle) const;
00155 
00160     void get(T& val, bool radian = true) const;
00161 
00163 
00166 
00170     operator T () const;
00171 
00175     T toRadian() const
00176   ;
00177 
00182     static T toRadian(const T& degree);
00183 
00187     T toDegree() const;
00188 
00193     static T toDegree(const T& radian);
00194 
00201     void normalize(Range range);
00202 
00205     void negate();
00206 
00209     TAngle operator + () const;
00210 
00213     TAngle operator - () const;
00214 
00219     TAngle& operator += (const TAngle& angle);
00220 
00225     TAngle& operator += (const T& val);
00226 
00231     TAngle operator + (const TAngle& angle);
00232 
00237     TAngle& operator -= (const TAngle& angle);
00238 
00243     TAngle& operator -= (const T& val);
00244 
00249     TAngle operator - (const TAngle& angle);
00250 
00255     TAngle& operator *= (const TAngle& angle);
00256 
00261     TAngle& operator *= (const T& val);
00262 
00267     TAngle& operator /= (const TAngle& angle)
00268       throw(Exception::DivisionByZero);
00269 
00274     TAngle& operator /= (const T& val)
00275       throw(Exception::DivisionByZero);
00276 
00281     TAngle operator / (const TAngle& val)
00282       throw(Exception::DivisionByZero);
00283 
00285 
00288 
00295     bool operator == (const TAngle& angle) const;
00296 
00303     bool operator != (const TAngle& angle) const;
00304 
00311     bool operator < (const TAngle& angle) const;
00312 
00319     bool operator < (const T& val) const;
00320 
00327     bool operator <= (const TAngle& angle) const;
00328 
00335     bool operator >= (const TAngle& angle) const;
00336 
00343     bool operator > (const TAngle& angle) const;
00344 
00351     bool isEquivalent(TAngle angle) const;
00352 
00354 
00357 
00362     bool isValid () const;
00363 
00370     void dump(std::ostream& s = std::cout, Size depth = 0) const;
00371 
00373 
00376 
00379     T value;
00380 
00382   };
00384 
00385   template <typename T>
00386   TAngle<T>::TAngle()
00387     : value((T)0)
00388   {
00389   }
00390 
00391   template <typename T>
00392   TAngle<T>::TAngle(const TAngle& angle)
00393     : value((T)angle.value)
00394   {
00395   }
00396 
00397   template <typename T>
00398   TAngle<T>::TAngle(const T& new_value, bool radian)
00399     : value((radian == true)
00400        ? (T)new_value 
00401        : (T)BALL_ANGLE_DEGREE_TO_RADIAN((double)new_value))
00402   {
00403   }
00404 
00405   template <typename T>
00406   void TAngle<T>::swap(TAngle& angle)
00407   {
00408     T temp = value;
00409     value = angle.value;
00410     angle.value = temp;
00411   }
00412 
00413   template <typename T>
00414   void TAngle<T>::set(const TAngle& angle)
00415   {
00416     value = angle.value;
00417   }
00418 
00419   template <typename T>
00420   void TAngle<T>::set(const T& new_value, bool radian)
00421   {
00422     value = (radian == true)
00423        ? new_value 
00424        : BALL_ANGLE_DEGREE_TO_RADIAN(new_value);
00425   }
00426 
00427   template <typename T>
00428   TAngle<T>& TAngle<T>::operator = (const TAngle& angle)
00429   {
00430     value = angle.value;
00431     return *this;
00432   }
00433 
00434   template <typename T>
00435   TAngle<T>& TAngle<T>::operator = (const T& new_value)
00436   {
00437     value = new_value;
00438     return *this;
00439   }
00440 
00441   template <typename T>
00442   void TAngle<T>::get(TAngle& angle) const
00443   {
00444     angle.value = value;
00445   }
00446 
00447   template <typename T>
00448   void TAngle<T>::get(T& val, bool radian) const
00449   {
00450     val = (radian == true)
00451            ? value 
00452            : BALL_ANGLE_RADIAN_TO_DEGREE(value);
00453   }
00454 
00455   template <typename T>
00456   TAngle<T>::operator T () const
00457   {
00458     return value;
00459   }
00460 
00461   template <typename T>
00462   T TAngle<T>::toRadian() const
00463   {
00464     return value;
00465   }
00466 
00467   template <typename T>
00468   T TAngle<T>::toRadian(const T& degree)
00469   {
00470     return BALL_ANGLE_DEGREE_TO_RADIAN(degree);
00471   }
00472 
00473   template <typename T>
00474   T TAngle<T>::toDegree() const
00475   {
00476     if (value == (T) 0.0) return (T) 0.0;
00477     return BALL_ANGLE_RADIAN_TO_DEGREE(value);
00478   }
00479 
00480   template <typename T>
00481   T TAngle<T>::toDegree(const T& radian)
00482   {
00483     if (radian == (T) 0.0) return (T) 0.0;
00484     return BALL_ANGLE_RADIAN_TO_DEGREE(radian);
00485   }
00486 
00487   template <typename T>
00488   void TAngle<T>::normalize(Range range)
00489   {
00490     if (range == RANGE__UNLIMITED)
00491     {
00492       return;
00493     }
00494 
00495     long mod_factor = (long)(value / (2 * Constants::PI));
00496     value -= mod_factor * (Constants::PI * 2);
00497 
00498     while (Maths::isGreater(value, (Constants::PI * 2)))
00499     {
00500       value -= (Constants::PI * 2);
00501     }
00502     while (Maths::isLess(value, -(Constants::PI * 2)))
00503     {
00504       value += (Constants::PI * 2);
00505     }
00506     if (range == RANGE__SIGNED) // invariant: -180 to 180:
00507     {
00508       if (Maths::isGreater(value, Constants::PI)) 
00509       {
00510         value -= (Constants::PI * 2);
00511       }
00512     } 
00513     else 
00514     { // invariant: 0 to 360:
00515       if (Maths::isLess(value, 0)) 
00516       {
00517         value += (Constants::PI * 2);
00518       }
00519     }
00520   }
00521 
00522   template <typename T>
00523   void TAngle<T>::negate() 
00524   {
00525     value = -value;
00526   }
00527 
00528   template <typename T>
00529   TAngle<T> TAngle<T>::operator + () const 
00530   {
00531     return *this;
00532   }
00533 
00534   template <typename T>
00535   TAngle<T> TAngle<T>::operator - () const 
00536   {
00537     return TAngle(-value);
00538   }
00539 
00540   template <typename T>
00541   TAngle<T>& TAngle<T>::operator += (const TAngle& angle) 
00542   {
00543     value += angle.value;
00544     return *this;
00545   }
00546 
00547   template <typename T>
00548   TAngle<T>& TAngle<T>::operator += (const T& val) 
00549   {
00550     value += val;
00551     return *this;
00552   }
00553 
00554   template <typename T>
00555   TAngle<T> TAngle<T>::operator + (const TAngle& angle)
00556   {
00557     return TAngle(value + angle.value);
00558   }
00559 
00560   template <typename T>
00561   TAngle<T>& TAngle<T>::operator -= (const TAngle& angle)
00562   {
00563     value -= angle.value;
00564     return *this;
00565   }
00566 
00567   template <typename T>
00568   TAngle<T>& TAngle<T>::operator -= (const T& val)
00569   {
00570     value -= val;
00571     return *this;
00572   }
00573 
00574   template <typename T>
00575   TAngle<T> TAngle<T>::operator - (const TAngle& angle) 
00576   {
00577     return TAngle(value - angle.value);
00578   }
00579 
00580   template <typename T>
00581   TAngle<T>& TAngle<T>::operator *= (const TAngle& angle)
00582   {
00583     value *= angle.value;
00584     return *this;
00585   }
00586 
00587   template <typename T>
00588   TAngle<T>& TAngle<T>::operator *= (const T& val)
00589   {
00590     value *= val;
00591     return *this;
00592   }
00593 
00594   template <typename T>
00595   TAngle<T>& TAngle<T>::operator /= (const TAngle& angle)
00596     throw(Exception::DivisionByZero)
00597   {
00598     if (angle.value == 0)
00599     {
00600       throw Exception::DivisionByZero(__FILE__, __LINE__);
00601     }
00602     value /= angle.value;
00603     return *this;
00604   }
00605 
00606 
00607   template <typename T>
00608   TAngle<T>& TAngle<T>::operator /= (const T& val) 
00609     throw(Exception::DivisionByZero)
00610   {
00611     if (val == 0)
00612     {
00613       throw Exception::DivisionByZero(__FILE__, __LINE__);
00614     }
00615 
00616     value /= val;
00617     return *this;
00618   }
00619 
00620 
00621   template <typename T>
00622   TAngle<T> TAngle<T>::operator / (const TAngle<T>& val) 
00623     throw(Exception::DivisionByZero)
00624   {
00625     if (val.value == 0)
00626     {
00627       throw Exception::DivisionByZero(__FILE__, __LINE__);
00628     }
00629 
00630     return TAngle(value / val.value);
00631   }
00632 
00633   template <typename T>
00634   bool TAngle<T>::operator == (const TAngle& angle) const
00635   {
00636     return Maths::isEqual(value, angle.value);
00637   }
00638 
00639   template <typename T>
00640   bool TAngle<T>::operator != (const TAngle& angle) const 
00641   {
00642     return Maths::isNotEqual(value, angle.value);
00643   }
00644 
00645   template <typename T>
00646   bool TAngle<T>::operator < (const TAngle& angle) const
00647   {
00648     return Maths::isLess(value, angle.value);
00649   }
00650 
00651   template <typename T>
00652   bool TAngle<T>::operator < (const T& val) const
00653   {
00654     return Maths::isLess(value, val);
00655   }
00656 
00657   template <typename T>
00658   bool TAngle<T>::operator <= (const TAngle& angle) const
00659   {
00660     return Maths::isLessOrEqual(value, angle.value);
00661   }
00662 
00663   template <typename T>
00664   bool TAngle<T>::operator >= (const TAngle& angle) const 
00665   {
00666     return Maths::isGreaterOrEqual(value, angle.value);
00667   }
00668 
00669   template <typename T>
00670   bool TAngle<T>::operator > (const TAngle& angle) const 
00671     
00672   {
00673     return Maths::isGreater(value, angle.value);
00674   }
00675 
00676   template <typename T>
00677   bool TAngle<T>::isEquivalent(TAngle angle) const
00678   {
00679     TAngle this_angle(*this);
00680 
00681     this_angle.normalize(RANGE__UNSIGNED);
00682     angle.normalize(RANGE__UNSIGNED);
00683 
00684     return (this_angle == angle);
00685   }
00686 
00687   template <typename T>
00688   bool TAngle<T>::isValid() const 
00689   {
00690     return true;
00691   }
00692 
00693   template <typename T>
00694   void TAngle<T>::dump(std::ostream& s, Size depth) const
00695   {
00696     BALL_DUMP_STREAM_PREFIX(s);
00697 
00698     BALL_DUMP_HEADER(s, this, this);
00699 
00700     BALL_DUMP_DEPTH(s, depth);
00701     s << "  value: " << value << std::endl;
00702 
00703     BALL_DUMP_STREAM_SUFFIX(s);
00704   }
00705 
00710   typedef TAngle<float> Angle;
00711 
00715   template <typename T>
00716   BALL_INLINE
00717   TAngle<T> operator * (const T& val, const TAngle<T>& angle)
00718   {
00719     return TAngle<T>(val * angle.value);
00720   }
00721 
00725   template <typename T>
00726   BALL_INLINE
00727   TAngle<T> operator + (const T& val, const TAngle<T>& angle) 
00728   {
00729     return TAngle<T>(val + angle.value);
00730   }
00731 
00735   template <typename T>
00736   BALL_INLINE
00737   TAngle<T> operator - (const T& val, const TAngle<T>& angle) 
00738   {
00739     return TAngle<T>(val - angle.value);
00740   }
00741 
00745   template <typename T>
00746   std::istream& operator >> (std::istream& s, TAngle<T>& angle)
00747   {
00748     char c;
00749     s >> c >> angle.value >> c;
00750     return s;
00751   }
00752 
00758   template <typename T>
00759   std::ostream& operator << (std::ostream& s, const TAngle<T>& angle)
00760   {
00761     s << '(' << angle.value << ')';
00762 
00763     return s;
00764   }
00765 
00766 } // namespace BALL
00767 
00768 #endif // BALL_MATHS_ANGLE_H