fit_rotations.cpp 6.6 KB

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