random_quaternion.cpp 2.3 KB

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