procrustes.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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_dec.h"
  10. template <
  11. typename DerivedX,
  12. typename DerivedY,
  13. typename Scalar,
  14. typename DerivedR,
  15. typename DerivedT>
  16. IGL_INLINE void igl::procrustes(
  17. const Eigen::MatrixBase<DerivedX>& X,
  18. const Eigen::MatrixBase<DerivedY>& Y,
  19. const bool includeScaling,
  20. const bool includeReflections,
  21. Scalar& scale,
  22. Eigen::PlainObjectBase<DerivedR>& R,
  23. Eigen::PlainObjectBase<DerivedT>& t)
  24. {
  25. assert (X.rows() == Y.rows() && "Same number of points");
  26. assert(X.cols() == Y.cols() && "Points have same dimensions");
  27. // Center data
  28. const Eigen::Matrix<typename DerivedX::Scalar, Eigen::Dynamic, 1> Xmean = X.colwise().mean();
  29. const Eigen::Matrix<typename DerivedY::Scalar, Eigen::Dynamic, 1> Ymean = Y.colwise().mean();
  30. Eigen::Matrix<typename DerivedX::Scalar, Eigen::Dynamic, Eigen::Dynamic> XC
  31. = X.rowwise() - Xmean.transpose();
  32. Eigen::Matrix<typename DerivedY::Scalar, Eigen::Dynamic, Eigen::Dynamic> YC
  33. = Y.rowwise() - Ymean.transpose();
  34. // Rotation
  35. Eigen::Matrix<typename DerivedX::Scalar, Eigen::Dynamic, Eigen::Dynamic> S = XC.transpose() * YC;
  36. Eigen::Matrix<typename DerivedT::Scalar, Eigen::Dynamic, Eigen::Dynamic> T;
  37. polar_dec(S, includeReflections, R, T);
  38. // Scale
  39. scale = 1.;
  40. if (includeScaling)
  41. {
  42. scale = (R.transpose() * S).trace() / (XC.array() * XC.array()).sum();
  43. }
  44. // Translation
  45. t = Ymean - scale*R.transpose()*Xmean;
  46. }
  47. template <
  48. typename DerivedX,
  49. typename DerivedY,
  50. typename Scalar,
  51. int DIM,
  52. int TType>
  53. IGL_INLINE void igl::procrustes(
  54. const Eigen::MatrixBase<DerivedX>& X,
  55. const Eigen::MatrixBase<DerivedY>& Y,
  56. const bool includeScaling,
  57. const bool includeReflections,
  58. Eigen::Transform<Scalar,DIM,TType>& T)
  59. {
  60. double scale;
  61. Eigen::MatrixXd R;
  62. Eigen::VectorXd t;
  63. procrustes(X,Y,includeScaling,includeReflections,scale,R,t);
  64. // Combine
  65. T = Eigen::Translation<Scalar,DIM>(t) * R * Eigen::Scaling(scale);
  66. }
  67. template <
  68. typename DerivedX,
  69. typename DerivedY,
  70. typename DerivedR,
  71. typename DerivedT>
  72. IGL_INLINE void igl::procrustes(
  73. const Eigen::MatrixBase<DerivedX>& X,
  74. const Eigen::MatrixBase<DerivedY>& Y,
  75. const bool includeScaling,
  76. const bool includeReflections,
  77. Eigen::PlainObjectBase<DerivedR>& S,
  78. Eigen::PlainObjectBase<DerivedT>& t)
  79. {
  80. double scale;
  81. procrustes(X,Y,includeScaling,includeReflections,scale,S,t);
  82. S *= scale;
  83. }
  84. template <
  85. typename DerivedX,
  86. typename DerivedY,
  87. typename DerivedR,
  88. typename DerivedT>
  89. IGL_INLINE void igl::procrustes(
  90. const Eigen::MatrixBase<DerivedX>& X,
  91. const Eigen::MatrixBase<DerivedY>& Y,
  92. Eigen::PlainObjectBase<DerivedR>& R,
  93. Eigen::PlainObjectBase<DerivedT>& t)
  94. {
  95. procrustes(X,Y,false,false,R,t);
  96. }
  97. template <
  98. typename DerivedX,
  99. typename DerivedY,
  100. typename Scalar,
  101. typename DerivedT>
  102. IGL_INLINE void igl::procrustes(
  103. const Eigen::MatrixBase<DerivedX>& X,
  104. const Eigen::MatrixBase<DerivedY>& Y,
  105. Eigen::Rotation2D<Scalar>& R,
  106. Eigen::PlainObjectBase<DerivedT>& t)
  107. {
  108. assert (X.cols() == 2 && Y.cols() == 2 && "Points must have dimension 2");
  109. Eigen::Matrix2d Rmat;
  110. procrustes(X,Y,false,false,Rmat,t);
  111. R.fromRotationMatrix(Rmat);
  112. }
  113. #ifdef IGL_STATIC_LIBRARY
  114. template void igl::procrustes<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, double, Eigen::Matrix<double, 3, 3, 0, 3, 3>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, const bool, const bool, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 3, 0, 3, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
  115. 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&, const bool, const bool, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 2, 0, 2, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 1, 0, 2, 1> >&);
  116. #endif