BALL
1.4.1
|
00001 // -*- Mode: C++; tab-width: 2; -*- 00002 // vi: set ts=2: 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 // no limitations 00070 RANGE__UNLIMITED = 0, 00071 // 0 <= angle <= 360, 0 <= angle <= (Constants::PI * 2) 00072 RANGE__UNSIGNED = 1, 00073 // -180 <= angle <= 180, -Constants::PI <= angle <= Constants::PI 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) // invariant: -180 to 180: 00505 { 00506 if (Maths::isGreater(value, Constants::PI)) 00507 { 00508 value -= (Constants::PI * 2); 00509 } 00510 } 00511 else 00512 { // invariant: 0 to 360: 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 } // namespace BALL 00762 00763 #endif // BALL_MATHS_ANGLE_H