fit_rotations.cpp 6.8 KB

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