00001
00002
00003
00004
00005 #ifndef BALL_MATHS_ANGLE_H
00006 #define BALL_MATHS_ANGLE_H
00007
00008 #ifndef BALL_COMMON_EXCEPTION_H
00009 # include <BALL/COMMON/exception.h>
00010 #endif
00011
00012 #ifndef BALL_COMMON_DEBUG_H
00013 # include <BALL/COMMON/debug.h>
00014 #endif
00015
00016 #ifndef BALL_COMMON_CREATE_H
00017 # include <BALL/COMMON/create.h>
00018 #endif
00019
00020 #ifndef BALL_MATHS_COMMON_H
00021 # include <BALL/MATHS/common.h>
00022 #endif
00023
00024 namespace BALL
00025 {
00031 template <typename T>
00032 class TAngle;
00033
00034 template <typename T>
00035 BALL_INLINE
00036 TAngle<T> operator * (const T& val, const TAngle<T>& angle);
00037
00038 template <typename T>
00039 BALL_INLINE
00040 TAngle<T> operator + (const T& val, const TAngle<T>& angle);
00041
00042 template <typename T>
00043 BALL_INLINE
00044 TAngle<T> operator - (const T& val, const TAngle<T>& angle);
00045
00051 template <typename T>
00052 class TAngle
00053 {
00054 public:
00055
00056 BALL_CREATE(TAngle<T>)
00057
00058
00061
00067 enum Range
00068 {
00069
00070 RANGE__UNLIMITED = 0,
00071
00072 RANGE__UNSIGNED = 1,
00073
00074 RANGE__SIGNED = 2
00075 };
00077
00080
00084 TAngle();
00085
00091 TAngle(const TAngle& angle);
00092
00100 explicit TAngle(const T& new_value, bool radian = true);
00101
00104 virtual ~TAngle()
00105 {
00106 }
00107
00111 virtual void clear()
00112 {
00113 value = (T)0;
00114 }
00116
00120
00123 void swap(TAngle& angle);
00124
00131 void set(const T& new_value, bool radian = true);
00132
00136 void set(const TAngle& angle);
00137
00140 TAngle& operator = (const TAngle& angle);
00141
00147 TAngle& operator = (const T& new_value);
00148
00152 void get(TAngle& angle) const;
00153
00158 void get(T& val, bool radian = true) const;
00159
00161
00164
00168 operator T () const;
00169
00173 T toRadian() const
00174 ;
00175
00180 static T toRadian(const T& degree);
00181
00185 T toDegree() const;
00186
00191 static T toDegree(const T& radian);
00192
00199 void normalize(Range range);
00200
00203 void negate();
00204
00207 TAngle operator + () const;
00208
00211 TAngle operator - () const;
00212
00217 TAngle& operator += (const TAngle& angle);
00218
00223 TAngle& operator += (const T& val);
00224
00229 TAngle operator + (const TAngle& angle);
00230
00235 TAngle& operator -= (const TAngle& angle);
00236
00241 TAngle& operator -= (const T& val);
00242
00247 TAngle operator - (const TAngle& angle);
00248
00253 TAngle& operator *= (const TAngle& angle);
00254
00259 TAngle& operator *= (const T& val);
00260
00266 TAngle& operator /= (const TAngle& angle);
00267
00273 TAngle& operator /= (const T& val);
00274
00280 TAngle operator / (const TAngle& val);
00281
00283
00286
00293 bool operator == (const TAngle& angle) const;
00294
00301 bool operator != (const TAngle& angle) const;
00302
00309 bool operator < (const TAngle& angle) const;
00310
00317 bool operator < (const T& val) const;
00318
00325 bool operator <= (const TAngle& angle) const;
00326
00333 bool operator >= (const TAngle& angle) const;
00334
00341 bool operator > (const TAngle& angle) const;
00342
00349 bool isEquivalent(TAngle angle) const;
00350
00352
00355
00360 bool isValid () const;
00361
00368 void dump(std::ostream& s = std::cout, Size depth = 0) const;
00369
00371
00374
00377 T value;
00378
00380 };
00382
00383 template <typename T>
00384 TAngle<T>::TAngle()
00385 : value((T)0)
00386 {
00387 }
00388
00389 template <typename T>
00390 TAngle<T>::TAngle(const TAngle& angle)
00391 : value((T)angle.value)
00392 {
00393 }
00394
00395 template <typename T>
00396 TAngle<T>::TAngle(const T& new_value, bool radian)
00397 : value((radian == true)
00398 ? (T)new_value
00399 : (T)BALL_ANGLE_DEGREE_TO_RADIAN((double)new_value))
00400 {
00401 }
00402
00403 template <typename T>
00404 void TAngle<T>::swap(TAngle& angle)
00405 {
00406 T temp = value;
00407 value = angle.value;
00408 angle.value = temp;
00409 }
00410
00411 template <typename T>
00412 void TAngle<T>::set(const TAngle& angle)
00413 {
00414 value = angle.value;
00415 }
00416
00417 template <typename T>
00418 void TAngle<T>::set(const T& new_value, bool radian)
00419 {
00420 value = (radian == true)
00421 ? new_value
00422 : BALL_ANGLE_DEGREE_TO_RADIAN(new_value);
00423 }
00424
00425 template <typename T>
00426 TAngle<T>& TAngle<T>::operator = (const TAngle& angle)
00427 {
00428 value = angle.value;
00429 return *this;
00430 }
00431
00432 template <typename T>
00433 TAngle<T>& TAngle<T>::operator = (const T& new_value)
00434 {
00435 value = new_value;
00436 return *this;
00437 }
00438
00439 template <typename T>
00440 void TAngle<T>::get(TAngle& angle) const
00441 {
00442 angle.value = value;
00443 }
00444
00445 template <typename T>
00446 void TAngle<T>::get(T& val, bool radian) const
00447 {
00448 val = (radian == true)
00449 ? value
00450 : BALL_ANGLE_RADIAN_TO_DEGREE(value);
00451 }
00452
00453 template <typename T>
00454 TAngle<T>::operator T () const
00455 {
00456 return value;
00457 }
00458
00459 template <typename T>
00460 T TAngle<T>::toRadian() const
00461 {
00462 return value;
00463 }
00464
00465 template <typename T>
00466 T TAngle<T>::toRadian(const T& degree)
00467 {
00468 return BALL_ANGLE_DEGREE_TO_RADIAN(degree);
00469 }
00470
00471 template <typename T>
00472 T TAngle<T>::toDegree() const
00473 {
00474 if (value == (T) 0.0) return (T) 0.0;
00475 return BALL_ANGLE_RADIAN_TO_DEGREE(value);
00476 }
00477
00478 template <typename T>
00479 T TAngle<T>::toDegree(const T& radian)
00480 {
00481 if (radian == (T) 0.0) return (T) 0.0;
00482 return BALL_ANGLE_RADIAN_TO_DEGREE(radian);
00483 }
00484
00485 template <typename T>
00486 void TAngle<T>::normalize(Range range)
00487 {
00488 if (range == RANGE__UNLIMITED)
00489 {
00490 return;
00491 }
00492
00493 long mod_factor = (long)(value / (2 * Constants::PI));
00494 value -= mod_factor * (Constants::PI * 2);
00495
00496 while (Maths::isGreater(value, (Constants::PI * 2)))
00497 {
00498 value -= (Constants::PI * 2);
00499 }
00500 while (Maths::isLess(value, -(Constants::PI * 2)))
00501 {
00502 value += (Constants::PI * 2);
00503 }
00504 if (range == RANGE__SIGNED)
00505 {
00506 if (Maths::isGreater(value, Constants::PI))
00507 {
00508 value -= (Constants::PI * 2);
00509 }
00510 }
00511 else
00512 {
00513 if (Maths::isLess(value, 0))
00514 {
00515 value += (Constants::PI * 2);
00516 }
00517 }
00518 }
00519
00520 template <typename T>
00521 void TAngle<T>::negate()
00522 {
00523 value = -value;
00524 }
00525
00526 template <typename T>
00527 TAngle<T> TAngle<T>::operator + () const
00528 {
00529 return *this;
00530 }
00531
00532 template <typename T>
00533 TAngle<T> TAngle<T>::operator - () const
00534 {
00535 return TAngle(-value);
00536 }
00537
00538 template <typename T>
00539 TAngle<T>& TAngle<T>::operator += (const TAngle& angle)
00540 {
00541 value += angle.value;
00542 return *this;
00543 }
00544
00545 template <typename T>
00546 TAngle<T>& TAngle<T>::operator += (const T& val)
00547 {
00548 value += val;
00549 return *this;
00550 }
00551
00552 template <typename T>
00553 TAngle<T> TAngle<T>::operator + (const TAngle& angle)
00554 {
00555 return TAngle(value + angle.value);
00556 }
00557
00558 template <typename T>
00559 TAngle<T>& TAngle<T>::operator -= (const TAngle& angle)
00560 {
00561 value -= angle.value;
00562 return *this;
00563 }
00564
00565 template <typename T>
00566 TAngle<T>& TAngle<T>::operator -= (const T& val)
00567 {
00568 value -= val;
00569 return *this;
00570 }
00571
00572 template <typename T>
00573 TAngle<T> TAngle<T>::operator - (const TAngle& angle)
00574 {
00575 return TAngle(value - angle.value);
00576 }
00577
00578 template <typename T>
00579 TAngle<T>& TAngle<T>::operator *= (const TAngle& angle)
00580 {
00581 value *= angle.value;
00582 return *this;
00583 }
00584
00585 template <typename T>
00586 TAngle<T>& TAngle<T>::operator *= (const T& val)
00587 {
00588 value *= val;
00589 return *this;
00590 }
00591
00592 template <typename T>
00593 TAngle<T>& TAngle<T>::operator /= (const TAngle& angle)
00594 {
00595 if (angle.value == 0)
00596 {
00597 throw Exception::DivisionByZero(__FILE__, __LINE__);
00598 }
00599 value /= angle.value;
00600 return *this;
00601 }
00602
00603
00604 template <typename T>
00605 TAngle<T>& TAngle<T>::operator /= (const T& val)
00606 {
00607 if (val == 0)
00608 {
00609 throw Exception::DivisionByZero(__FILE__, __LINE__);
00610 }
00611
00612 value /= val;
00613 return *this;
00614 }
00615
00616
00617 template <typename T>
00618 TAngle<T> TAngle<T>::operator / (const TAngle<T>& val)
00619 {
00620 if (val.value == 0)
00621 {
00622 throw Exception::DivisionByZero(__FILE__, __LINE__);
00623 }
00624
00625 return TAngle(value / val.value);
00626 }
00627
00628 template <typename T>
00629 bool TAngle<T>::operator == (const TAngle& angle) const
00630 {
00631 return Maths::isEqual(value, angle.value);
00632 }
00633
00634 template <typename T>
00635 bool TAngle<T>::operator != (const TAngle& angle) const
00636 {
00637 return Maths::isNotEqual(value, angle.value);
00638 }
00639
00640 template <typename T>
00641 bool TAngle<T>::operator < (const TAngle& angle) const
00642 {
00643 return Maths::isLess(value, angle.value);
00644 }
00645
00646 template <typename T>
00647 bool TAngle<T>::operator < (const T& val) const
00648 {
00649 return Maths::isLess(value, val);
00650 }
00651
00652 template <typename T>
00653 bool TAngle<T>::operator <= (const TAngle& angle) const
00654 {
00655 return Maths::isLessOrEqual(value, angle.value);
00656 }
00657
00658 template <typename T>
00659 bool TAngle<T>::operator >= (const TAngle& angle) const
00660 {
00661 return Maths::isGreaterOrEqual(value, angle.value);
00662 }
00663
00664 template <typename T>
00665 bool TAngle<T>::operator > (const TAngle& angle) const
00666
00667 {
00668 return Maths::isGreater(value, angle.value);
00669 }
00670
00671 template <typename T>
00672 bool TAngle<T>::isEquivalent(TAngle angle) const
00673 {
00674 TAngle this_angle(*this);
00675
00676 this_angle.normalize(RANGE__UNSIGNED);
00677 angle.normalize(RANGE__UNSIGNED);
00678
00679 return (this_angle == angle);
00680 }
00681
00682 template <typename T>
00683 bool TAngle<T>::isValid() const
00684 {
00685 return true;
00686 }
00687
00688 template <typename T>
00689 void TAngle<T>::dump(std::ostream& s, Size depth) const
00690 {
00691 BALL_DUMP_STREAM_PREFIX(s);
00692
00693 BALL_DUMP_HEADER(s, this, this);
00694
00695 BALL_DUMP_DEPTH(s, depth);
00696 s << " value: " << value << std::endl;
00697
00698 BALL_DUMP_STREAM_SUFFIX(s);
00699 }
00700
00705 typedef TAngle<float> Angle;
00706
00710 template <typename T>
00711 BALL_INLINE
00712 TAngle<T> operator * (const T& val, const TAngle<T>& angle)
00713 {
00714 return TAngle<T>(val * angle.value);
00715 }
00716
00720 template <typename T>
00721 BALL_INLINE
00722 TAngle<T> operator + (const T& val, const TAngle<T>& angle)
00723 {
00724 return TAngle<T>(val + angle.value);
00725 }
00726
00730 template <typename T>
00731 BALL_INLINE
00732 TAngle<T> operator - (const T& val, const TAngle<T>& angle)
00733 {
00734 return TAngle<T>(val - angle.value);
00735 }
00736
00740 template <typename T>
00741 std::istream& operator >> (std::istream& s, TAngle<T>& angle)
00742 {
00743 char c;
00744 s >> c >> angle.value >> c;
00745 return s;
00746 }
00747
00753 template <typename T>
00754 std::ostream& operator << (std::ostream& s, const TAngle<T>& angle)
00755 {
00756 s << '(' << angle.value << ')';
00757
00758 return s;
00759 }
00760
00761 }
00762
00763 #endif // BALL_MATHS_ANGLE_H