quat_to_axis_angle.cpp 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #include "quat_to_axis_angle.h"
  2. #include "EPS.h"
  3. #include "PI.h"
  4. #include <cmath>
  5. #include <cstdio>
  6. //
  7. // http://www.antisphere.com/Wiki/tools:anttweakbar
  8. template <typename Q_type>
  9. IGL_INLINE void igl::quat_to_axis_angle(
  10. const Q_type *q,
  11. Q_type *axis,
  12. Q_type & angle)
  13. {
  14. using namespace igl;
  15. if( fabs(q[3])>(1.0 + igl::EPS<Q_type>()) )
  16. {
  17. //axis[0] = axis[1] = axis[2] = 0; // no, keep the previous value
  18. angle = 0;
  19. }
  20. else
  21. {
  22. double a;
  23. if( q[3]>=1.0f )
  24. a = 0; // and keep V
  25. else if( q[3]<=-1.0f )
  26. a = PI; // and keep V
  27. else if( fabs(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3])<igl::EPS_SQ<Q_type>())
  28. {
  29. a = 0;
  30. }else
  31. {
  32. a = acos(q[3]);
  33. if( a*angle<0 ) // Preserve the sign of angle
  34. a = -a;
  35. double f = 1.0f / sin(a);
  36. axis[0] = q[0] * f;
  37. axis[1] = q[1] * f;
  38. axis[2] = q[2] * f;
  39. }
  40. angle = 2.0*a;
  41. }
  42. // if( angle>FLOAT_PI )
  43. // angle -= 2.0f*FLOAT_PI;
  44. // else if( angle<-FLOAT_PI )
  45. // angle += 2.0f*FLOAT_PI;
  46. //angle = RadToDeg(angle);
  47. if( fabs(angle)<igl::EPS<Q_type>()&& fabs(axis[0]*axis[0]+axis[1]*axis[1]+axis[2]*axis[2])<igl::EPS_SQ<Q_type>())
  48. {
  49. axis[0] = 1.0e-7; // all components cannot be null
  50. }
  51. }
  52. template <typename Q_type>
  53. IGL_INLINE void igl::quat_to_axis_angle_deg(
  54. const Q_type *q,
  55. Q_type *axis,
  56. Q_type & angle)
  57. {
  58. igl::quat_to_axis_angle(q,axis,angle);
  59. angle = angle*(180.0/PI);
  60. }
  61. #ifndef IGL_NO_HEADER
  62. // Explicit template instanciation
  63. template void igl::quat_to_axis_angle<float>(float const*, float*, float&);
  64. template void igl::quat_to_axis_angle_deg<float>(float const*, float*, float&);
  65. #endif