fit_rotations.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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 "fit_rotations.h"
  9. #include "polar_svd3x3.h"
  10. #include <igl/repmat.h>
  11. #include <igl/verbose.h>
  12. #include <igl/polar_dec.h>
  13. #include <igl/polar_svd.h>
  14. #include <iostream>
  15. template <typename DerivedS, typename DerivedD>
  16. IGL_INLINE void igl::fit_rotations(
  17. const Eigen::PlainObjectBase<DerivedS> & S,
  18. Eigen::PlainObjectBase<DerivedD> & R)
  19. {
  20. using namespace std;
  21. const int dim = S.cols();
  22. const int nr = S.rows()/dim;
  23. assert(nr * dim == S.rows());
  24. // resize output
  25. R.resize(dim,dim*nr); // hopefully no op (should be already allocated)
  26. //std::cout<<"S=["<<std::endl<<S<<std::endl<<"];"<<std::endl;
  27. //MatrixXd si(dim,dim);
  28. Eigen::Matrix<typename DerivedS::Scalar,3,3> si;// = Eigen::Matrix3d::Identity();
  29. // loop over number of rotations we're computing
  30. for(int r = 0;r<nr;r++)
  31. {
  32. // build this covariance matrix
  33. for(int i = 0;i<dim;i++)
  34. {
  35. for(int j = 0;j<dim;j++)
  36. {
  37. si(i,j) = S(i*nr+r,j);
  38. }
  39. }
  40. Eigen::Matrix<typename DerivedD::Scalar,3,3> ri;
  41. Eigen::Matrix<typename DerivedD::Scalar,3,3> ti;
  42. //polar_dec(si,ri,ti);
  43. //polar_svd(si,ri,ti);
  44. polar_svd3x3(si, ri);
  45. assert(ri.determinant() >= 0);
  46. #ifndef FIT_ROTATIONS_ALLOW_FLIPS
  47. // Check for reflection
  48. if(ri.determinant() < 0)
  49. {
  50. cerr<<"Error: Warning: flipping is wrong..."<<endl;
  51. assert(false && "This is wrong. Need to flip column in U and recompute R = U*V'");
  52. // flip sign of last row
  53. ri.row(2) *= -1;
  54. }
  55. assert(ri.determinant() >= 0);
  56. #endif
  57. // Not sure why polar_dec computes transpose...
  58. R.block(0,r*dim,dim,dim) = ri.block(0,0,dim,dim).transpose();
  59. }
  60. }
  61. template <typename DerivedS, typename DerivedD>
  62. IGL_INLINE void igl::fit_rotations_planar(
  63. const Eigen::PlainObjectBase<DerivedS> & S,
  64. Eigen::PlainObjectBase<DerivedD> & R)
  65. {
  66. using namespace std;
  67. const int dim = S.cols();
  68. const int nr = S.rows()/dim;
  69. assert(nr * dim == S.rows());
  70. // resize output
  71. R.resize(dim,dim*nr); // hopefully no op (should be already allocated)
  72. Eigen::Matrix<typename DerivedS::Scalar,2,2> si;
  73. // loop over number of rotations we're computing
  74. for(int r = 0;r<nr;r++)
  75. {
  76. // build this covariance matrix
  77. for(int i = 0;i<2;i++)
  78. {
  79. for(int j = 0;j<2;j++)
  80. {
  81. si(i,j) = S(i*nr+r,j);
  82. }
  83. }
  84. Eigen::Matrix<typename DerivedD::Scalar,2,2> ri;
  85. Eigen::Matrix<typename DerivedD::Scalar,2,2> ti;
  86. igl::polar_svd(si,ri,ti);
  87. #ifndef FIT_ROTATIONS_ALLOW_FLIPS
  88. // Check for reflection
  89. if(ri.determinant() < 0)
  90. {
  91. cerr<<"Error: Warning: flipping is wrong..."<<endl;
  92. assert(false && "This is wrong. Need to flip column in U and recompute R = U*V'");
  93. // flip sign of last row
  94. ri.row(1) *= -1;
  95. }
  96. assert(ri.determinant() >= 0);
  97. #endif
  98. // Not sure why polar_dec computes transpose...
  99. R.block(0,r*dim,2,2) = ri.block(0,0,2,2).transpose();
  100. // Set remaining part to identity
  101. R(0,r*3+2) = 0;
  102. R(1,r*3+2) = 0;
  103. R(2,r*3+0) = 0;
  104. R(2,r*3+1) = 0;
  105. R(2,r*3+2) = 1;
  106. }
  107. }
  108. #ifdef __SSE__
  109. IGL_INLINE void igl::fit_rotations_SSE(
  110. const Eigen::MatrixXf & S,
  111. Eigen::MatrixXf & R)
  112. {
  113. const int cStep = 4;
  114. assert(S.cols() == 3);
  115. const int dim = 3; //S.cols();
  116. const int nr = S.rows()/dim;
  117. assert(nr * dim == S.rows());
  118. // resize output
  119. R.resize(dim,dim*nr); // hopefully no op (should be already allocated)
  120. Eigen::Matrix<float, 3*cStep, 3> siBig;
  121. // using SSE decompose cStep matrices at a time:
  122. int r = 0;
  123. for( ; r<nr; r+=cStep)
  124. {
  125. int numMats = cStep;
  126. if (r + cStep >= nr) numMats = nr - r;
  127. // build siBig:
  128. for (int k=0; k<numMats; k++)
  129. {
  130. for(int i = 0;i<dim;i++)
  131. {
  132. for(int j = 0;j<dim;j++)
  133. {
  134. siBig(i + 3*k, j) = S(i*nr + r + k, j);
  135. }
  136. }
  137. }
  138. Eigen::Matrix<float, 3*cStep, 3> ri;
  139. polar_svd3x3_sse(siBig, ri);
  140. for (int k=0; k<cStep; k++)
  141. assert(ri.block(3*k, 0, 3, 3).determinant() >= 0);
  142. // Not sure why polar_dec computes transpose...
  143. for (int k=0; k<numMats; k++)
  144. {
  145. R.block(0, (r + k)*dim, dim, dim) = ri.block(3*k, 0, dim, dim).transpose();
  146. }
  147. }
  148. }
  149. IGL_INLINE void igl::fit_rotations_SSE(
  150. const Eigen::MatrixXd & S,
  151. Eigen::MatrixXd & R)
  152. {
  153. const Eigen::MatrixXf Sf = S.cast<float>();
  154. Eigen::MatrixXf Rf;
  155. fit_rotations_SSE(Sf,Rf);
  156. R = Rf.cast<double>();
  157. }
  158. #endif
  159. #ifdef __AVX__
  160. IGL_INLINE void igl::fit_rotations_AVX(
  161. const Eigen::MatrixXf & S,
  162. Eigen::MatrixXf & R)
  163. {
  164. const int cStep = 8;
  165. assert(S.cols() == 3);
  166. const int dim = 3; //S.cols();
  167. const int nr = S.rows()/dim;
  168. assert(nr * dim == S.rows());
  169. // resize output
  170. R.resize(dim,dim*nr); // hopefully no op (should be already allocated)
  171. Eigen::Matrix<float, 3*cStep, 3> siBig;
  172. // using SSE decompose cStep matrices at a time:
  173. int r = 0;
  174. for( ; r<nr; r+=cStep)
  175. {
  176. int numMats = cStep;
  177. if (r + cStep >= nr) numMats = nr - r;
  178. // build siBig:
  179. for (int k=0; k<numMats; k++)
  180. {
  181. for(int i = 0;i<dim;i++)
  182. {
  183. for(int j = 0;j<dim;j++)
  184. {
  185. siBig(i + 3*k, j) = S(i*nr + r + k, j);
  186. }
  187. }
  188. }
  189. Eigen::Matrix<float, 3*cStep, 3> ri;
  190. polar_svd3x3_avx(siBig, ri);
  191. for (int k=0; k<cStep; k++)
  192. assert(ri.block(3*k, 0, 3, 3).determinant() >= 0);
  193. // Not sure why polar_dec computes transpose...
  194. for (int k=0; k<numMats; k++)
  195. {
  196. R.block(0, (r + k)*dim, dim, dim) = ri.block(3*k, 0, dim, dim).transpose();
  197. }
  198. }
  199. }
  200. #endif
  201. // Explicit template instanciation
  202. template void igl::fit_rotations<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
  203. template void igl::fit_rotations_planar<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);