quat_to_axis_angle.cpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  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. if( fabs(q[3])>(1.0 + igl::EPS<Q_type>()) )
  22. {
  23. //axis[0] = axis[1] = axis[2] = 0; // no, keep the previous value
  24. angle = 0;
  25. }
  26. else
  27. {
  28. double a;
  29. if( q[3]>=1.0f )
  30. a = 0; // and keep V
  31. else if( q[3]<=-1.0f )
  32. a = PI; // and keep V
  33. else if( fabs(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3])<igl::EPS_SQ<Q_type>())
  34. {
  35. a = 0;
  36. }else
  37. {
  38. a = acos(q[3]);
  39. if( a*angle<0 ) // Preserve the sign of angle
  40. a = -a;
  41. double f = 1.0f / sin(a);
  42. axis[0] = q[0] * f;
  43. axis[1] = q[1] * f;
  44. axis[2] = q[2] * f;
  45. }
  46. angle = 2.0*a;
  47. }
  48. // if( angle>FLOAT_PI )
  49. // angle -= 2.0f*FLOAT_PI;
  50. // else if( angle<-FLOAT_PI )
  51. // angle += 2.0f*FLOAT_PI;
  52. //angle = RadToDeg(angle);
  53. 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>())
  54. {
  55. axis[0] = 1.0e-7; // all components cannot be null
  56. }
  57. }
  58. template <typename Q_type>
  59. IGL_INLINE void igl::quat_to_axis_angle_deg(
  60. const Q_type *q,
  61. Q_type *axis,
  62. Q_type & angle)
  63. {
  64. igl::quat_to_axis_angle(q,axis,angle);
  65. angle = angle*(180.0/PI);
  66. }
  67. #ifdef IGL_STATIC_LIBRARY
  68. // Explicit template specialization
  69. template void igl::quat_to_axis_angle<float>(float const*, float*, float&);
  70. template void igl::quat_to_axis_angle_deg<float>(float const*, float*, float&);
  71. #endif