quat_to_axis_angle.cpp 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "quat_to_axis_angle.h"
  9. #include "EPS.h"
  10. #include "PI.h"
  11. #include <cmath>
  12. #include <cstdio>
  13. //
  14. // http://www.antisphere.com/Wiki/tools:anttweakbar
  15. template <typename Q_type>
  16. IGL_INLINE void igl::quat_to_axis_angle(
  17. const Q_type *q,
  18. Q_type *axis,
  19. Q_type & angle)
  20. {
  21. using namespace igl;
  22. if( fabs(q[3])>(1.0 + igl::EPS<Q_type>()) )
  23. {
  24. //axis[0] = axis[1] = axis[2] = 0; // no, keep the previous value
  25. angle = 0;
  26. }
  27. else
  28. {
  29. double a;
  30. if( q[3]>=1.0f )
  31. a = 0; // and keep V
  32. else if( q[3]<=-1.0f )
  33. a = PI; // and keep V
  34. else if( fabs(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3])<igl::EPS_SQ<Q_type>())
  35. {
  36. a = 0;
  37. }else
  38. {
  39. a = acos(q[3]);
  40. if( a*angle<0 ) // Preserve the sign of angle
  41. a = -a;
  42. double f = 1.0f / sin(a);
  43. axis[0] = q[0] * f;
  44. axis[1] = q[1] * f;
  45. axis[2] = q[2] * f;
  46. }
  47. angle = 2.0*a;
  48. }
  49. // if( angle>FLOAT_PI )
  50. // angle -= 2.0f*FLOAT_PI;
  51. // else if( angle<-FLOAT_PI )
  52. // angle += 2.0f*FLOAT_PI;
  53. //angle = RadToDeg(angle);
  54. 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>())
  55. {
  56. axis[0] = 1.0e-7; // all components cannot be null
  57. }
  58. }
  59. template <typename Q_type>
  60. IGL_INLINE void igl::quat_to_axis_angle_deg(
  61. const Q_type *q,
  62. Q_type *axis,
  63. Q_type & angle)
  64. {
  65. igl::quat_to_axis_angle(q,axis,angle);
  66. angle = angle*(180.0/PI);
  67. }
  68. #ifndef IGL_NO_HEADER
  69. // Explicit template instanciation
  70. template void igl::quat_to_axis_angle<float>(float const*, float*, float&);
  71. template void igl::quat_to_axis_angle_deg<float>(float const*, float*, float&);
  72. #endif