1 // -*- Mode: C++; tab-width: 2; -*- 2 // vi: set ts=2: 3 // 4 5 #ifndef BALL_MATHS_ANGLE_H 6 #define BALL_MATHS_ANGLE_H 7 8 #ifndef BALL_COMMON_EXCEPTION_H 9 # include <BALL/COMMON/exception.h> 10 #endif 11 12 #ifndef BALL_COMMON_DEBUG_H 13 # include <BALL/COMMON/debug.h> 14 #endif 15 16 #ifndef BALL_COMMON_CREATE_H 17 # include <BALL/COMMON/create.h> 18 #endif 19 20 #ifndef BALL_MATHS_COMMON_H 21 # include <BALL/MATHS/common.h> 22 #endif 23 24 namespace BALL 25 { 26 /** \defgroup Angle Representation of angles. 27 class \link BALL::TAngle TAngle \endlink and class \link Angle Angle \endlink 28 \ingroup Primitives 29 */ 30 //@{ 31 template <typename T> 32 class TAngle; 33 34 template <typename T> 35 BALL_INLINE 36 TAngle<T> operator * (const T& val, const TAngle<T>& angle); 37 38 template <typename T> 39 BALL_INLINE 40 TAngle<T> operator + (const T& val, const TAngle<T>& angle); 41 42 template <typename T> 43 BALL_INLINE 44 TAngle<T> operator - (const T& val, const TAngle<T>& angle); 45 46 /** Generic Angle Class. 47 Use this class to describe angles. The TAngle class permits the conversion 48 from degree to radians and is the return type of all functions used to calculate 49 angles. 50 */ 51 template <typename T> 52 class TAngle 53 { 54 public: 55 56 BALL_CREATE(TAngle<T>) 57 58 /** @name Enums 59 */ 60 //@{ 61 62 /** form of the angle range: 63 <tt>RANGE__UNLIMITED = 0</tt> no limitations 64 <tt>RANGE__UNSIGNED = 1</tt> 0 <= angle <= 360, 0 <= angle <= PI * 2 65 <tt>RANGE__SIGNED = 2</tt> -180 <= angle <= 180, -PI <= angle <= PI 66 */ 67 enum Range 68 { 69 // no limitations 70 RANGE__UNLIMITED = 0, 71 // 0 <= angle <= 360, 0 <= angle <= (Constants::PI * 2) 72 RANGE__UNSIGNED = 1, 73 // -180 <= angle <= 180, -Constants::PI <= angle <= Constants::PI 74 RANGE__SIGNED = 2 75 }; 76 //@} 77 /** @name Constructors and Destructors 78 */ 79 //@{ 80 81 /** Default constructor. 82 Creates a new angle object. Its value is set to 0. 83 */ 84 TAngle(); 85 86 /** Copy constructor. 87 Create a copy of a TAngle object. Copies are always 88 shallow. 89 @param angle the object to be copied 90 */ 91 TAngle(const TAngle& angle); 92 93 /** Detailed constructor. 94 Create a new angle object and set its value to 95 <tt>new_value</tt>. <tt>radian</tt> determines whether <tt>new_value</tt> 96 is in radians or in degrees. 97 @param new_value the value of the angle object 98 @param radian <b>true</b> if <tt>new_value</tt> is in radians, <tt>false</tt> otherwise 99 */ 100 explicit TAngle(const T& new_value, bool radian = true); 101 102 /** Destructor. 103 */ ~TAngle()104 virtual ~TAngle() 105 { 106 } 107 108 /** Clear method 109 The value is set to 0. 110 */ clear()111 virtual void clear() 112 { 113 value = (T)0; 114 } 115 //@} 116 117 /** @name Assignment 118 */ 119 //@{ 120 121 /** Swap the contents of two angles. 122 */ 123 void swap(TAngle& angle); 124 125 /** Assign a new value to the angle. 126 <tt>radian</tt> determines whether <tt>new_value</tt> 127 is in radians or in degrees. 128 @param new_value the value of the angle object 129 @param radian <b>true</b> if <tt>new_value</tt> is in radians, <tt>false</tt> otherwise 130 */ 131 void set(const T& new_value, bool radian = true); 132 133 /** Assign an Angle object from another. 134 @param angle the angle object to be assigned from 135 */ 136 void set(const TAngle& angle); 137 138 /** Assignment operator 139 */ 140 TAngle& operator = (const TAngle& angle); 141 142 /** Assignment operator for floats. 143 Assign a float value to the angle. 144 The assigned value has to be in radians! 145 @param new_value the new value 146 */ 147 TAngle& operator = (const T& new_value); 148 149 /** Assign the value to another angle. 150 @param angle the angle to assign the value to 151 */ 152 void get(TAngle& angle) const; 153 154 /** Assign the value to a variable of type <tt>T</tt>. 155 @param val the variable to assign the value to 156 @param radian if set to <tt>true</tt> assigns the value in radians (default). 157 */ 158 void get(T& val, bool radian = true) const; 159 160 //@} 161 /** @name Accessors 162 */ 163 //@{ 164 165 /** Cast operator 166 @return value in radians 167 */ 168 operator T () const; 169 170 /** Return the value of the angle 171 @return value in radians 172 */ 173 T toRadian() const 174 ; 175 176 /** Calculate radians from degrees 177 @param degree the value in degrees 178 @return T the value in radians 179 */ 180 static T toRadian(const T& degree); 181 182 /** Return the value of the angle 183 @return value in degrees 184 */ 185 T toDegree() const; 186 187 /** Calculate degrees from radians 188 @param radian the value in radians 189 @return T the value in degrees 190 */ 191 static T toDegree(const T& radian); 192 193 /** Normalize the angle over a given range. 194 <tt>RANGE__UNLIMITED = 0</tt> no limitations. 195 <tt>RANGE__UNSIGNED = 1</tt> \f$0 \le \mathtt{angle} \le 360, 0 \le angle \le 2 \pi\f$. 196 <tt>RANGE__SIGNED = 2</tt> \f$-180 \le \mathtt{angle} \le 180, -\pi \le \mathtt{angle} \le \pi\f$. 197 @param range the range of the angle 198 */ 199 void normalize(Range range); 200 201 /** Negate the angle 202 */ 203 void negate(); 204 205 /** Positive sign. 206 */ 207 TAngle operator + () const; 208 209 /** Negative sign. 210 */ 211 TAngle operator - () const; 212 213 /** Addition operator. 214 @param angle the angle to add 215 @return TAngle, {\em *this} 216 */ 217 TAngle& operator += (const TAngle& angle); 218 219 /** Add a value to this angle. 220 @param val the value to add 221 @return TAngle, {\em *this} 222 */ 223 TAngle& operator += (const T& val); 224 225 /** Addition operator. 226 @param angle the angle to add 227 @return TAngle, the new angle 228 */ 229 TAngle operator + (const TAngle& angle); 230 231 /** Substraction operator. 232 @param angle the angle to substract 233 @return TAngle, {\em *this} 234 */ 235 TAngle& operator -= (const TAngle& angle); 236 237 /** Substract a value from this angle. 238 @param val the value to substract 239 @return TAngle, {\em *this} 240 */ 241 TAngle& operator -= (const T& val); 242 243 /** Subtraction an angle from this angle. 244 @param angle the angle to substract 245 @return TAngle, the new angle 246 */ 247 TAngle operator - (const TAngle& angle); 248 249 /** Multiply an angle with this angle. 250 @param angle the angle to multiply by 251 @return TAngle, {\em *this} 252 */ 253 TAngle& operator *= (const TAngle& angle); 254 255 /** Multiply a value with this angle. 256 @param val the value to multiply by 257 @return TAngle, {\em *this} 258 */ 259 TAngle& operator *= (const T& val); 260 261 /** Division operator. 262 @param angle the angle to divide by 263 @return TAngle, {\em *this} 264 @throw Exception::DivisionByZero if angle is zero 265 */ 266 TAngle& operator /= (const TAngle& angle); 267 268 /** Divide this angle by a value. 269 @param val the angle to divide by 270 @return TAngle, {\em *this} 271 @throw Exception::DivisionByZero if val is zero 272 */ 273 TAngle& operator /= (const T& val); 274 275 /** Divide this angle by a value. 276 @param val the angle to divide by 277 @return TAngle, the new angle 278 @throw Exception::DivisionByZero if val is zero 279 */ 280 TAngle operator / (const TAngle& val); 281 282 //@} 283 /** @name Predicates 284 */ 285 //@{ 286 287 /** Equality operator. 288 This test uses Maths::isEqual instead of comparing the 289 values directly. 290 @param angle the angle to compare with 291 @return bool, <b>true</b> if the two angles are equal 292 */ 293 bool operator == (const TAngle& angle) const; 294 295 /** Inequality operator 296 This test uses Maths::isNotEqual instead of comparing the 297 values directly. 298 @param angle the angle to compare with 299 @return bool, <b>true</b> if the two angles are not equal 300 */ 301 bool operator != (const TAngle& angle) const; 302 303 /** Is less operator. 304 This test uses Maths::isLess instead of comparing the 305 values directly. 306 @param angle the angle to compare with 307 @return bool, <b>true</b> if {\em *this} angle is smaller than <tt>value</tt> 308 */ 309 bool operator < (const TAngle& angle) const; 310 311 /** Is less operator. 312 This test uses Maths::isLess instead of comparing the 313 values directly. 314 @param val the value to compare with 315 @return bool, <b>true</b> if {\em *this} angle is smaller than <tt>value</tt> 316 */ 317 bool operator < (const T& val) const; 318 319 /** Is less or equal operator. 320 This test uses Maths::isLessOrEqual instead of comparing the 321 values directly. 322 @param angle the angle to compare with 323 @return bool, <b>true</b> if {\em *this} angle is smaller or equal than <tt>value</tt> 324 */ 325 bool operator <= (const TAngle& angle) const; 326 327 /** Is greater or equal operator. 328 This test uses Maths::isGreaterOrEqual instead of comparing the 329 values directly. 330 @param angle the angle to compare with 331 @return bool, <b>true</b> if {\em *this} angle is greater or equal than <tt>value</tt> 332 */ 333 bool operator >= (const TAngle& angle) const; 334 335 /** Is greater operator. 336 This test uses Maths::isGreater instead of comparing the 337 values directly. 338 @param angle the angle to compare with 339 @return bool, <b>true</b> if {\em *this} angle is greater than <tt>value</tt> 340 */ 341 bool operator > (const TAngle& angle) const; 342 343 /** Test whether two angles are equivalent. 344 Both angles are normalized and afterwards compared with Maths::isEqual 345 instead of comparing the values directly. 346 @param angle the angle to compare with 347 @return bool, <b>true</b> if {\em *this} angle is equal to <tt>value</tt> 348 */ 349 bool isEquivalent(TAngle angle) const; 350 351 //@} 352 /** @name Debugging and Diagnostics 353 */ 354 //@{ 355 356 /** Test whether instance is valid. 357 Always returns true 358 @return bool <b>true</b> 359 */ 360 bool isValid () const; 361 362 /** Internal state dump. 363 Dump the current internal state of {\em *this} to 364 the output ostream <b> s </b> with dumping depth <b> depth </b>. 365 @param s - output stream where to output the internal state of {\em *this} 366 @param depth - the dumping depth 367 */ 368 void dump(std::ostream& s = std::cout, Size depth = 0) const; 369 370 //@} 371 /** @name Attributes 372 */ 373 //@{ 374 375 /** The value 376 */ 377 T value; 378 379 //@} 380 }; 381 //@} 382 383 template <typename T> TAngle()384 TAngle<T>::TAngle() 385 : value((T)0) 386 { 387 } 388 389 template <typename T> TAngle(const TAngle & angle)390 TAngle<T>::TAngle(const TAngle& angle) 391 : value((T)angle.value) 392 { 393 } 394 395 template <typename T> TAngle(const T & new_value,bool radian)396 TAngle<T>::TAngle(const T& new_value, bool radian) 397 : value((radian == true) 398 ? (T)new_value 399 : (T)BALL_ANGLE_DEGREE_TO_RADIAN((double)new_value)) 400 { 401 } 402 403 template <typename T> swap(TAngle & angle)404 void TAngle<T>::swap(TAngle& angle) 405 { 406 T temp = value; 407 value = angle.value; 408 angle.value = temp; 409 } 410 411 template <typename T> set(const TAngle & angle)412 void TAngle<T>::set(const TAngle& angle) 413 { 414 value = angle.value; 415 } 416 417 template <typename T> set(const T & new_value,bool radian)418 void TAngle<T>::set(const T& new_value, bool radian) 419 { 420 value = (radian == true) 421 ? new_value 422 : BALL_ANGLE_DEGREE_TO_RADIAN(new_value); 423 } 424 425 template <typename T> 426 TAngle<T>& TAngle<T>::operator = (const TAngle& angle) 427 { 428 value = angle.value; 429 return *this; 430 } 431 432 template <typename T> 433 TAngle<T>& TAngle<T>::operator = (const T& new_value) 434 { 435 value = new_value; 436 return *this; 437 } 438 439 template <typename T> get(TAngle & angle)440 void TAngle<T>::get(TAngle& angle) const 441 { 442 angle.value = value; 443 } 444 445 template <typename T> get(T & val,bool radian)446 void TAngle<T>::get(T& val, bool radian) const 447 { 448 val = (radian == true) 449 ? value 450 : BALL_ANGLE_RADIAN_TO_DEGREE(value); 451 } 452 453 template <typename T> T()454 TAngle<T>::operator T () const 455 { 456 return value; 457 } 458 459 template <typename T> toRadian()460 T TAngle<T>::toRadian() const 461 { 462 return value; 463 } 464 465 template <typename T> toRadian(const T & degree)466 T TAngle<T>::toRadian(const T& degree) 467 { 468 return BALL_ANGLE_DEGREE_TO_RADIAN(degree); 469 } 470 471 template <typename T> toDegree()472 T TAngle<T>::toDegree() const 473 { 474 if (value == (T) 0.0) return (T) 0.0; 475 return BALL_ANGLE_RADIAN_TO_DEGREE(value); 476 } 477 478 template <typename T> toDegree(const T & radian)479 T TAngle<T>::toDegree(const T& radian) 480 { 481 if (radian == (T) 0.0) return (T) 0.0; 482 return BALL_ANGLE_RADIAN_TO_DEGREE(radian); 483 } 484 485 template <typename T> normalize(Range range)486 void TAngle<T>::normalize(Range range) 487 { 488 if (range == RANGE__UNLIMITED) 489 { 490 return; 491 } 492 493 long mod_factor = (long)(value / (2 * Constants::PI)); 494 value -= mod_factor * (Constants::PI * 2); 495 496 while (Maths::isGreater(value, (Constants::PI * 2))) 497 { 498 value -= (Constants::PI * 2); 499 } 500 while (Maths::isLess(value, -(Constants::PI * 2))) 501 { 502 value += (Constants::PI * 2); 503 } 504 if (range == RANGE__SIGNED) // invariant: -180 to 180: 505 { 506 if (Maths::isGreater(value, Constants::PI)) 507 { 508 value -= (Constants::PI * 2); 509 } 510 } 511 else 512 { // invariant: 0 to 360: 513 if (Maths::isLess(value, 0)) 514 { 515 value += (Constants::PI * 2); 516 } 517 } 518 } 519 520 template <typename T> negate()521 void TAngle<T>::negate() 522 { 523 value = -value; 524 } 525 526 template <typename T> 527 TAngle<T> TAngle<T>::operator + () const 528 { 529 return *this; 530 } 531 532 template <typename T> 533 TAngle<T> TAngle<T>::operator - () const 534 { 535 return TAngle(-value); 536 } 537 538 template <typename T> 539 TAngle<T>& TAngle<T>::operator += (const TAngle& angle) 540 { 541 value += angle.value; 542 return *this; 543 } 544 545 template <typename T> 546 TAngle<T>& TAngle<T>::operator += (const T& val) 547 { 548 value += val; 549 return *this; 550 } 551 552 template <typename T> 553 TAngle<T> TAngle<T>::operator + (const TAngle& angle) 554 { 555 return TAngle(value + angle.value); 556 } 557 558 template <typename T> 559 TAngle<T>& TAngle<T>::operator -= (const TAngle& angle) 560 { 561 value -= angle.value; 562 return *this; 563 } 564 565 template <typename T> 566 TAngle<T>& TAngle<T>::operator -= (const T& val) 567 { 568 value -= val; 569 return *this; 570 } 571 572 template <typename T> 573 TAngle<T> TAngle<T>::operator - (const TAngle& angle) 574 { 575 return TAngle(value - angle.value); 576 } 577 578 template <typename T> 579 TAngle<T>& TAngle<T>::operator *= (const TAngle& angle) 580 { 581 value *= angle.value; 582 return *this; 583 } 584 585 template <typename T> 586 TAngle<T>& TAngle<T>::operator *= (const T& val) 587 { 588 value *= val; 589 return *this; 590 } 591 592 template <typename T> 593 TAngle<T>& TAngle<T>::operator /= (const TAngle& angle) 594 { 595 if (angle.value == 0) 596 { 597 throw Exception::DivisionByZero(__FILE__, __LINE__); 598 } 599 value /= angle.value; 600 return *this; 601 } 602 603 604 template <typename T> 605 TAngle<T>& TAngle<T>::operator /= (const T& val) 606 { 607 if (val == 0) 608 { 609 throw Exception::DivisionByZero(__FILE__, __LINE__); 610 } 611 612 value /= val; 613 return *this; 614 } 615 616 617 template <typename T> 618 TAngle<T> TAngle<T>::operator / (const TAngle<T>& val) 619 { 620 if (val.value == 0) 621 { 622 throw Exception::DivisionByZero(__FILE__, __LINE__); 623 } 624 625 return TAngle(value / val.value); 626 } 627 628 template <typename T> 629 bool TAngle<T>::operator == (const TAngle& angle) const 630 { 631 return Maths::isEqual(value, angle.value); 632 } 633 634 template <typename T> 635 bool TAngle<T>::operator != (const TAngle& angle) const 636 { 637 return Maths::isNotEqual(value, angle.value); 638 } 639 640 template <typename T> 641 bool TAngle<T>::operator < (const TAngle& angle) const 642 { 643 return Maths::isLess(value, angle.value); 644 } 645 646 template <typename T> 647 bool TAngle<T>::operator < (const T& val) const 648 { 649 return Maths::isLess(value, val); 650 } 651 652 template <typename T> 653 bool TAngle<T>::operator <= (const TAngle& angle) const 654 { 655 return Maths::isLessOrEqual(value, angle.value); 656 } 657 658 template <typename T> 659 bool TAngle<T>::operator >= (const TAngle& angle) const 660 { 661 return Maths::isGreaterOrEqual(value, angle.value); 662 } 663 664 template <typename T> 665 bool TAngle<T>::operator > (const TAngle& angle) const 666 667 { 668 return Maths::isGreater(value, angle.value); 669 } 670 671 template <typename T> isEquivalent(TAngle angle)672 bool TAngle<T>::isEquivalent(TAngle angle) const 673 { 674 TAngle this_angle(*this); 675 676 this_angle.normalize(RANGE__UNSIGNED); 677 angle.normalize(RANGE__UNSIGNED); 678 679 return (this_angle == angle); 680 } 681 682 template <typename T> isValid()683 bool TAngle<T>::isValid() const 684 { 685 return true; 686 } 687 688 template <typename T> dump(std::ostream & s,Size depth)689 void TAngle<T>::dump(std::ostream& s, Size depth) const 690 { 691 BALL_DUMP_STREAM_PREFIX(s); 692 693 BALL_DUMP_HEADER(s, this, this); 694 695 BALL_DUMP_DEPTH(s, depth); 696 s << " value: " << value << std::endl; 697 698 BALL_DUMP_STREAM_SUFFIX(s); 699 } 700 701 /** The Default Angle Type. 702 If double precision is not needed, <tt>TAngle<float></tt> should 703 be used. It is predefined as <tt>Angle</tt> for convenience. 704 */ 705 typedef TAngle<float> Angle; 706 707 /** Multiplication operator. 708 Multiplies a number with an angle. 709 */ 710 template <typename T> 711 BALL_INLINE 712 TAngle<T> operator * (const T& val, const TAngle<T>& angle) 713 { 714 return TAngle<T>(val * angle.value); 715 } 716 717 /** Plus operator. 718 Adds a number with an angle (in rad!) 719 */ 720 template <typename T> 721 BALL_INLINE 722 TAngle<T> operator + (const T& val, const TAngle<T>& angle) 723 { 724 return TAngle<T>(val + angle.value); 725 } 726 727 /** Minus operator. 728 Subtracts the value of an angle (in rad!) from a number. 729 */ 730 template <typename T> 731 BALL_INLINE 732 TAngle<T> operator - (const T& val, const TAngle<T>& angle) 733 { 734 return TAngle<T>(val - angle.value); 735 } 736 737 /** Input Operator. 738 Reads the value (in radians) of an angle from an instream using T::operator >> 739 */ 740 template <typename T> 741 std::istream& operator >> (std::istream& s, TAngle<T>& angle) 742 { 743 char c; 744 s >> c >> angle.value >> c; 745 return s; 746 } 747 748 /** Output Operator. 749 Writes the value of the angle to an output stream. 750 The stream operator <tt>operator <<</tt> has to be defined 751 for the template parameter <tt>T</tt>. 752 */ 753 template <typename T> 754 std::ostream& operator << (std::ostream& s, const TAngle<T>& angle) 755 { 756 s << '(' << angle.value << ')'; 757 758 return s; 759 } 760 761 } // namespace BALL 762 763 #endif // BALL_MATHS_ANGLE_H 764