random_quaternion.cpp 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 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 "random_quaternion.h"
  9. template <typename Scalar>
  10. IGL_INLINE Eigen::Quaternion<Scalar> igl::random_quaternion()
  11. {
  12. const auto & unit_rand = []()->Scalar
  13. {
  14. return ((Scalar)rand() / (Scalar)RAND_MAX);
  15. };
  16. #ifdef false
  17. // http://mathproofs.blogspot.com/2005/05/uniformly-distributed-random-unit.html
  18. const Scalar t0 = 2.*M_PI*unit_rand();
  19. const Scalar t1 = acos(1.-2.*unit_rand());
  20. const Scalar t2 = 0.5*(M_PI*unit_rand() + acos(unit_rand()));
  21. return Eigen::Quaternion<Scalar>(
  22. 1.*sin(t0)*sin(t1)*sin(t2),
  23. 1.*cos(t0)*sin(t1)*sin(t2),
  24. 1.*cos(t1)*sin(t2),
  25. 1.*cos(t2));
  26. #elif false
  27. // "Uniform Random Rotations" [Shoemake 1992] method 1
  28. const auto & uurand = [&unit_rand]()->Scalar
  29. {
  30. return unit_rand()*2.-1.;
  31. };
  32. Scalar x = uurand();
  33. Scalar y = uurand();
  34. Scalar z = uurand();
  35. Scalar w = uurand();
  36. const auto & hype = [&uurand](Scalar & x, Scalar & y)->Scalar
  37. {
  38. Scalar s1;
  39. while((s1 = x*x + y*y) > 1.0)
  40. {
  41. x = uurand();
  42. y = uurand();
  43. }
  44. return s1;
  45. };
  46. Scalar s1 = hype(x,y);
  47. Scalar s2 = hype(z,w);
  48. Scalar num1 = -2.*log(s1);
  49. Scalar num2 = -2.*log(s2);
  50. Scalar r = num1 + num2;
  51. Scalar root1 = sqrt((num1/s1)/r);
  52. Scalar root2 = sqrt((num2/s2)/r);
  53. return Eigen::Quaternion<Scalar>(
  54. x*root1,
  55. y*root1,
  56. z*root2,
  57. w*root2);
  58. #else
  59. // Shoemake method 2
  60. const Scalar x0 = unit_rand();
  61. const Scalar x1 = unit_rand();
  62. const Scalar x2 = unit_rand();
  63. const Scalar r1 = sqrt(1.0 - x0);
  64. const Scalar r2 = sqrt(x0);
  65. const Scalar t1 = 2.*M_PI*x1;
  66. const Scalar t2 = 2.*M_PI*x2;
  67. const Scalar c1 = cos(t1);
  68. const Scalar s1 = sin(t1);
  69. const Scalar c2 = cos(t2);
  70. const Scalar s2 = sin(t2);
  71. return Eigen::Quaternion<Scalar>(
  72. s1*r1,
  73. c1*r1,
  74. s2*r2,
  75. c2*r2);
  76. #endif
  77. }
  78. #ifdef IGL_STATIC_LIBRARY
  79. // Explicit template specialization
  80. template Eigen::Quaternion<double, 0> igl::random_quaternion<double>();
  81. #endif