00001
00002
00003
00004
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
00072 RANGE__UNLIMITED = 0,
00073
00074 RANGE__UNSIGNED = 1,
00075
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)
00507 {
00508 if (Maths::isGreater(value, Constants::PI))
00509 {
00510 value -= (Constants::PI * 2);
00511 }
00512 }
00513 else
00514 {
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 }
00767
00768 #endif // BALL_MATHS_ANGLE_H