snap_to_canonical_view_quat.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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 "snap_to_canonical_view_quat.h"
  9. #include "canonical_quaternions.h"
  10. #include "normalize_quat.h"
  11. #include <cstdio>
  12. #include <cassert>
  13. // Note: For the canonical view quaternions it should be completely possible to
  14. // determine this anaylitcally. That is the max_distance should be a
  15. // theoretical known value
  16. // Also: I'm not sure it matters in this case, but. We are dealing with
  17. // quaternions on the 4d unit sphere, but measuring distance in general 4d
  18. // space (i.e. not geodesics on the sphere). Probably something with angles
  19. // would be better.
  20. template <typename Q_type>
  21. IGL_INLINE bool igl::snap_to_canonical_view_quat(
  22. const Q_type* q,
  23. const Q_type threshold,
  24. Q_type* s)
  25. {
  26. // Copy input into output
  27. // CANNOT use std::copy here according to:
  28. // http://www.cplusplus.com/reference/algorithm/copy/
  29. s[0] = q[0];
  30. s[1] = q[1];
  31. s[2] = q[2];
  32. s[3] = q[3];
  33. // Normalize input quaternion
  34. Q_type qn[4];
  35. bool valid_len =
  36. igl::normalize_quat(q,qn);
  37. // If normalizing valid then don't bother
  38. if(!valid_len)
  39. {
  40. return false;
  41. }
  42. // 0.290019
  43. const Q_type MAX_DISTANCE = 0.4;
  44. Q_type min_distance = 2*MAX_DISTANCE;
  45. int min_index = -1;
  46. double min_sign = 0;
  47. // loop over canonical view quaternions
  48. for(double sign = -1;sign<=1;sign+=2)
  49. {
  50. for(int i = 0; i<NUM_CANONICAL_VIEW_QUAT; i++)
  51. {
  52. Q_type distance = 0.0;
  53. // loop over coordinates
  54. for(int j = 0;j<4;j++)
  55. {
  56. // Double cast because of bug in llvm version 4.2 with -O3
  57. distance +=
  58. (qn[j]-sign*igl::CANONICAL_VIEW_QUAT<Q_type>(i,j))*
  59. (qn[j]-sign*igl::CANONICAL_VIEW_QUAT<Q_type>(i,j));
  60. }
  61. if(min_distance > distance)
  62. {
  63. min_distance = distance;
  64. min_index = i;
  65. min_sign = sign;
  66. }
  67. }
  68. }
  69. if(MAX_DISTANCE < min_distance)
  70. {
  71. fprintf(
  72. stderr,
  73. "ERROR: found new max MIN_DISTANCE: %g\n"
  74. "PLEASE update snap_to_canonical_quat()",
  75. min_distance);
  76. }
  77. assert(min_distance < MAX_DISTANCE);
  78. assert(min_index >= 0);
  79. if( min_distance/MAX_DISTANCE <= threshold)
  80. {
  81. // loop over coordinates
  82. for(int j = 0;j<4;j++)
  83. {
  84. s[j] = min_sign*igl::CANONICAL_VIEW_QUAT<Q_type>(min_index,j);
  85. }
  86. return true;
  87. }
  88. return false;
  89. }
  90. template <typename Scalarq, typename Scalars>
  91. IGL_INLINE bool igl::snap_to_canonical_view_quat(
  92. const Eigen::Quaternion<Scalarq> & q,
  93. const double threshold,
  94. Eigen::Quaternion<Scalars> & s)
  95. {
  96. return snap_to_canonical_view_quat<Scalars>(
  97. q.coeffs().data(),threshold,s.coeffs().data());
  98. }
  99. #ifdef IGL_STATIC_LIBRARY
  100. // Explicit template specialization
  101. // generated by autoexplicit.sh
  102. template bool igl::snap_to_canonical_view_quat<double>(const double*, double, double*);
  103. // generated by autoexplicit.sh
  104. template bool igl::snap_to_canonical_view_quat<float>(const float*, float, float*);
  105. template bool igl::snap_to_canonical_view_quat<float, float>(Eigen::Quaternion<float, 0> const&, double, Eigen::Quaternion<float, 0>&);
  106. template bool igl::snap_to_canonical_view_quat<double, double>(Eigen::Quaternion<double, 0> const&, double, Eigen::Quaternion<double, 0>&);
  107. #endif