fit_rotations.cpp 6.1 KB

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