procrustes.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 Stefan Brugger <[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 "procrustes.h"
  9. #include "polar_svd.h"
  10. #include "polar_dec.h"
  11. template <
  12. typename DerivedX,
  13. typename DerivedY,
  14. typename Scalar,
  15. typename DerivedR,
  16. typename DerivedT>
  17. IGL_INLINE void igl::procrustes(
  18. const Eigen::MatrixBase<DerivedX>& X,
  19. const Eigen::MatrixBase<DerivedY>& Y,
  20. bool includeScaling,
  21. bool includeReflections,
  22. Scalar& scale,
  23. Eigen::PlainObjectBase<DerivedR>& R,
  24. Eigen::PlainObjectBase<DerivedT>& t)
  25. {
  26. using namespace Eigen;
  27. assert (X.rows() == Y.rows() && "Same number of points");
  28. assert(X.cols() == Y.cols() && "Points have same dimensions");
  29. // Center data
  30. const VectorXd Xmean = X.colwise().mean();
  31. const VectorXd Ymean = Y.colwise().mean();
  32. Matrix<typename DerivedX::Scalar, Dynamic, Dynamic> XC
  33. = X.rowwise() - Xmean.transpose();
  34. Matrix<typename DerivedY::Scalar, Dynamic, Dynamic> YC
  35. = Y.rowwise() - Ymean.transpose();
  36. // Scale
  37. scale = 1.;
  38. if (includeScaling)
  39. {
  40. double scaleX = XC.norm() / XC.rows();
  41. double scaleY = YC.norm() / YC.rows();
  42. scale = scaleY/scaleX;
  43. XC *= scale;
  44. assert (std::abs(XC.norm() / XC.rows() - scaleY) < 1e-8);
  45. }
  46. // Rotation
  47. MatrixXd S = XC.transpose() * YC;
  48. MatrixXd T;
  49. if (includeReflections)
  50. {
  51. polar_dec(S,R,T);
  52. }else
  53. {
  54. polar_svd(S,R,T);
  55. }
  56. // R.transposeInPlace();
  57. // Translation
  58. t = Ymean - scale*R.transpose()*Xmean;
  59. }
  60. template <
  61. typename DerivedX,
  62. typename DerivedY,
  63. typename Scalar,
  64. int DIM,
  65. int TType>
  66. IGL_INLINE void igl::procrustes(
  67. const Eigen::MatrixBase<DerivedX>& X,
  68. const Eigen::MatrixBase<DerivedY>& Y,
  69. bool includeScaling,
  70. bool includeReflections,
  71. Eigen::Transform<Scalar,DIM,TType>& T)
  72. {
  73. using namespace Eigen;
  74. double scale;
  75. MatrixXd R;
  76. VectorXd t;
  77. procrustes(X,Y,includeScaling,includeReflections,scale,R,t);
  78. // Combine
  79. T = Translation<Scalar,DIM>(t) * R * Scaling(scale);
  80. }
  81. template <
  82. typename DerivedX,
  83. typename DerivedY,
  84. typename DerivedR,
  85. typename DerivedT>
  86. IGL_INLINE void igl::procrustes(
  87. const Eigen::MatrixBase<DerivedX>& X,
  88. const Eigen::MatrixBase<DerivedY>& Y,
  89. bool includeScaling,
  90. bool includeReflections,
  91. Eigen::PlainObjectBase<DerivedR>& S,
  92. Eigen::PlainObjectBase<DerivedT>& t)
  93. {
  94. double scale;
  95. procrustes(X,Y,includeScaling,includeReflections,scale,S,t);
  96. S *= scale;
  97. }
  98. template <
  99. typename DerivedX,
  100. typename DerivedY,
  101. typename DerivedR,
  102. typename DerivedT>
  103. IGL_INLINE void igl::procrustes(
  104. const Eigen::MatrixBase<DerivedX>& X,
  105. const Eigen::MatrixBase<DerivedY>& Y,
  106. Eigen::PlainObjectBase<DerivedR>& R,
  107. Eigen::PlainObjectBase<DerivedT>& t)
  108. {
  109. procrustes(X,Y,false,false,R,t);
  110. }
  111. template <
  112. typename DerivedX,
  113. typename DerivedY,
  114. typename Scalar,
  115. typename DerivedT>
  116. IGL_INLINE void igl::procrustes(
  117. const Eigen::MatrixBase<DerivedX>& X,
  118. const Eigen::MatrixBase<DerivedY>& Y,
  119. Eigen::Rotation2D<Scalar>& R,
  120. Eigen::PlainObjectBase<DerivedT>& t)
  121. {
  122. using namespace Eigen;
  123. assert (X.cols() == 2 && Y.cols() == 2 && "Points must have dimension 2");
  124. Matrix2d Rmat;
  125. procrustes(X,Y,false,false,Rmat,t);
  126. R.fromRotationMatrix(Rmat);
  127. }
  128. #ifdef IGL_STATIC_LIBRARY
  129. template void igl::procrustes<Eigen::Matrix<double, 3, 2, 0, 3, 2>, Eigen::Matrix<double, 3, 2, 0, 3, 2>, double, Eigen::Matrix<double, 2, 2, 0, 2, 2>, Eigen::Matrix<double, 2, 1, 0, 2, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 2, 0, 3, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 3, 2, 0, 3, 2> > const&, bool, bool, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 2, 0, 2, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 1, 0, 2, 1> >&);
  130. #endif