procrustes.cpp 3.9 KB

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