procrustes.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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 <typename DerivedV, typename Scalar, typename DerivedR, typename DerivedT>
  12. IGL_INLINE void igl::procrustes(
  13. const Eigen::PlainObjectBase<DerivedV>& X,
  14. const Eigen::PlainObjectBase<DerivedV>& Y,
  15. bool includeScaling,
  16. bool includeReflections,
  17. Scalar& scale,
  18. Eigen::PlainObjectBase<DerivedR>& R,
  19. Eigen::PlainObjectBase<DerivedT>& t)
  20. {
  21. using namespace Eigen;
  22. assert (X.rows() == Y.rows() && "Same number of points");
  23. assert(X.cols() == Y.cols() && "Points have same dimensions");
  24. // Center data
  25. const VectorXd Xmean = X.colwise().mean();
  26. const VectorXd Ymean = Y.colwise().mean();
  27. MatrixXd XC = X.rowwise() - Xmean.transpose();
  28. MatrixXd YC = Y.rowwise() - Ymean.transpose();
  29. // Scale
  30. scale = 1.;
  31. if (includeScaling)
  32. {
  33. double scaleX = XC.norm() / XC.rows();
  34. double scaleY = YC.norm() / YC.rows();
  35. scale = scaleY/scaleX;
  36. XC *= scale;
  37. assert (abs(XC.norm() / XC.rows() - scaleY) < 1e-8);
  38. }
  39. // Rotation
  40. MatrixXd S = XC.transpose() * YC;
  41. MatrixXd T;
  42. if (includeReflections)
  43. polar_dec(S,R,T);
  44. else
  45. polar_svd(S,R,T);
  46. R.transposeInPlace();
  47. // Translation
  48. t = Ymean - scale*R.transpose()*Xmean;
  49. }
  50. template <typename DerivedV, typename DerivedR, typename DerivedT>
  51. IGL_INLINE void igl::procrustes(
  52. const Eigen::PlainObjectBase<DerivedV>& X,
  53. const Eigen::PlainObjectBase<DerivedV>& Y,
  54. bool includeScaling,
  55. bool includeReflections,
  56. Eigen::PlainObjectBase<DerivedR>& S,
  57. Eigen::PlainObjectBase<DerivedT>& t)
  58. {
  59. double scale;
  60. procrustes(X,Y,includeScaling,includeReflections,scale,S,t);
  61. S *= scale;
  62. }
  63. template <typename DerivedV, typename Scalar, int DIM, int TType>
  64. IGL_INLINE void igl::procrustes(
  65. const Eigen::PlainObjectBase<DerivedV>& X,
  66. const Eigen::PlainObjectBase<DerivedV>& Y,
  67. bool includeScaling,
  68. bool includeReflections,
  69. Eigen::Transform<Scalar,DIM,TType>& T)
  70. {
  71. double scale;
  72. MatrixXd R;
  73. VectorXd t;
  74. procrustes(X,Y,includeScaling,includeReflections,scale,R,t);
  75. // Combine
  76. T = Translation<Scalar,DIM>(t) * R * Scaling(scale);
  77. }
  78. template <typename DerivedV, typename DerivedR, typename DerivedT>
  79. IGL_INLINE void igl::procrustes(
  80. const Eigen::PlainObjectBase<DerivedV>& X,
  81. const Eigen::PlainObjectBase<DerivedV>& Y,
  82. Eigen::PlainObjectBase<DerivedR>& R,
  83. Eigen::PlainObjectBase<DerivedT>& t)
  84. {
  85. double scale;
  86. procrustes(X,Y,false,false,R,t);
  87. }
  88. template <typename DerivedV, typename Scalar, typename DerivedT>
  89. IGL_INLINE void igl::procrustes(
  90. const Eigen::PlainObjectBase<DerivedV>& X,
  91. const Eigen::PlainObjectBase<DerivedV>& Y,
  92. Eigen::Rotation2D<Scalar>& R,
  93. Eigen::PlainObjectBase<DerivedT>& t)
  94. {
  95. assert (X.cols() == 2 && Y.cols() == 2 && "Points must have dimension 2");
  96. Matrix2d Rmat;
  97. procrustes(X,Y,false,false,Rmat,t);
  98. R.fromRotationMatrix(Rmat);
  99. }