$search
00001 00008 /***************************************************************************** 00009 ** Ifdefs 00010 *****************************************************************************/ 00011 00012 #ifndef ECL_GEOMETRY_ANGLE_HPP_ 00013 #define ECL_GEOMETRY_ANGLE_HPP_ 00014 00015 /***************************************************************************** 00016 ** Includes 00017 *****************************************************************************/ 00018 00019 #include <cmath> 00020 #include <ecl/config/macros.hpp> 00021 #include <ecl/linear_algebra.hpp> 00022 #include <ecl/type_traits/fundamental_types.hpp> 00023 #include <ecl/mpl/enable_if.hpp> 00024 #include <ecl/math/constants.hpp> 00025 00026 /***************************************************************************** 00027 ** Namespaces 00028 *****************************************************************************/ 00029 00030 namespace ecl { 00031 00039 template <typename T> 00040 ECL_PUBLIC T radians_to_degrees(const T &radians, typename enable_if<ecl::is_float<T> >::type* dummy = 0) { 00041 static const T rads_to_degs = 180.0/pi; 00042 return radians*rads_to_degs; 00043 } 00044 00052 template <typename T> 00053 ECL_PUBLIC T degrees_to_radians(const T °rees, typename enable_if<ecl::is_float<T> >::type* dummy = 0) { 00054 static const T degs_to_rads = pi/180.0; 00055 return degrees*degs_to_rads; 00056 } 00057 00067 ECL_PUBLIC const float& wrap_angle(float &angle); 00068 00079 ECL_PUBLIC float wrap_angle(const float &angle); 00089 ECL_PUBLIC const double& wrap_angle(double &angle); 00090 00101 ECL_PUBLIC double wrap_angle(const double &angle); 00102 00103 /***************************************************************************** 00104 ** Interface [Angle] 00105 *****************************************************************************/ 00111 template <class T, typename Enable = void> 00112 class ECL_LOCAL Angle { 00113 private: 00120 Angle() {}; 00121 }; 00122 00134 template <typename T> 00135 class ECL_PUBLIC Angle<T, typename enable_if<is_float<T> >::type> { 00136 public: 00137 /********************* 00138 ** Typedefs 00139 **********************/ 00140 typedef ecl::linear_algebra::Matrix<T,2,2> RotationMatrix; 00149 Angle(const T &angle = 0.0) : value(angle) { wrap_angle(value); } 00154 Angle(const RotationMatrix &rotation) { 00155 value = std::atan2(rotation(1,0),rotation(0,0)); 00156 } 00157 00167 const Angle<T>& operator=(const T &angle); 00168 /********************* 00169 ** Math Operators 00170 **********************/ 00179 Angle<T> operator+(const T &angle) const; 00188 Angle<T> operator+(const Angle<T> &angle) const; 00196 void operator+=(const T &angle); 00204 void operator+=(const Angle<T> &angle); 00213 Angle<T> operator-(const T &angle) const; 00222 Angle<T> operator-(const Angle<T> &angle) const; 00230 void operator-=(const T &angle); 00238 void operator-=(const Angle<T> &angle); 00247 Angle<T> operator*(const T &scalar) const; 00255 void operator*=(const T &scalar); 00256 00257 /********************* 00258 ** Casting 00259 **********************/ 00269 operator const T&() const { return value; } 00280 T degrees(); 00281 00286 RotationMatrix rotationMatrix() const { 00287 T c = std::cos(value); 00288 T s = std::sin(value); 00289 return (RotationMatrix() << c, -s, s, c).finished(); 00290 } 00291 00305 static Angle<T> Degrees(const T &angle); 00319 static Angle<T> Radians(const T &angle); 00320 00321 private: 00322 T value; 00323 }; 00324 00329 /***************************************************************************** 00330 ** Implementation 00331 *****************************************************************************/ 00332 00333 template <typename T> 00334 T Angle<T, typename enable_if<is_float<T> >::type>::degrees() { 00335 return radians_to_degrees(value); 00336 } 00337 00338 template <typename T> 00339 const Angle<T>& Angle<T, typename enable_if<is_float<T> >::type>::operator=(const T &angle) { 00340 value = angle; 00341 wrap_angle(value); 00342 return *this; 00343 } 00344 00345 /***************************************************************************** 00346 ** Operators 00347 *****************************************************************************/ 00348 00349 template <typename T> 00350 Angle<T> Angle<T, typename enable_if<is_float<T> >::type>::operator+(const T &angle) const { 00351 return Angle<T>(wrap_angle(value+angle)); 00352 } 00353 00354 template <typename T> 00355 Angle<T> Angle<T, typename enable_if<is_float<T> >::type>::operator+(const Angle<T> &angle) const { 00356 return Angle<T>(wrap_angle(value+angle.value)); 00357 } 00358 00359 template <typename T> 00360 void Angle<T, typename enable_if<is_float<T> >::type>::operator+=(const T &angle) { 00361 value += angle; 00362 wrap_angle(value); 00363 } 00364 00365 template <typename T> 00366 void Angle<T, typename enable_if<is_float<T> >::type>::operator+=(const Angle<T> &angle) { 00367 value += angle.value; 00368 wrap_angle(value); 00369 } 00370 00371 template <typename T> 00372 Angle<T> Angle<T, typename enable_if<is_float<T> >::type>::operator-(const T &angle) const { 00373 return Angle<T>(wrap_angle(value-angle)); 00374 } 00375 00376 template <typename T> 00377 Angle<T> Angle<T, typename enable_if<is_float<T> >::type>::operator-(const Angle<T> &angle) const { 00378 return Angle<T>(wrap_angle(value-angle.value)); 00379 } 00380 00381 template <typename T> 00382 void Angle<T, typename enable_if<is_float<T> >::type>::operator-=(const T &angle) { 00383 value -= angle; 00384 wrap_angle(value); 00385 } 00386 00387 template <typename T> 00388 void Angle<T, typename enable_if<is_float<T> >::type>::operator-=(const Angle<T> &angle) { 00389 value -= angle.value; 00390 wrap_angle(value); 00391 } 00392 00393 template <typename T> 00394 Angle<T> Angle<T, typename enable_if<is_float<T> >::type>::operator*(const T &scalar) const { 00395 return Angle<T>(wrap_angle(scalar*value)); 00396 } 00397 00398 template <typename T> 00399 void Angle<T, typename enable_if<is_float<T> >::type>::operator*=(const T &scalar) { 00400 value *= scalar; 00401 wrap_angle(value); 00402 } 00403 00404 /***************************************************************************** 00405 ** Statics 00406 *****************************************************************************/ 00407 00408 template <typename T> 00409 Angle<T> Angle<T, typename enable_if<is_float<T> >::type>::Degrees(const T &angle) { 00410 return Angle<T>(degrees_to_radians(angle)); 00411 } 00412 00413 template <typename T> 00414 Angle<T> Angle<T, typename enable_if<is_float<T> >::type>::Radians(const T &angle) { 00415 return Angle<T>(angle); 00416 } 00421 } // namespace ecl 00422 00423 #endif /* ECL_GEOMETRY_ANGLE_HPP_ */