procrustes.cpp 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  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, int DIM, int TType>
  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. Eigen::Transform<Scalar,DIM,TType>& T)
  18. {
  19. using namespace Eigen;
  20. assert (X.rows() == Y.rows() && "Same number of points");
  21. assert(X.cols() == Y.cols() && "Points have same dimensions");
  22. // Center data
  23. const VectorXd Xmean = X.colwise().mean();
  24. const VectorXd Ymean = Y.colwise().mean();
  25. MatrixXd XC = X.rowwise() - Xmean.transpose();
  26. MatrixXd YC = Y.rowwise() - Ymean.transpose();
  27. // Determine scale
  28. double scale = 1.;
  29. if (includeScaling)
  30. {
  31. double scaleX = XC.norm() / XC.rows();
  32. double scaleY = YC.norm() / YC.rows();
  33. scale = scaleY/scaleX;
  34. XC *= scale;
  35. assert (abs(XC.norm() / XC.rows() - scaleY) < 1e-8);
  36. }
  37. // Rotation
  38. MatrixXd S = XC.transpose() * YC;
  39. Matrix<Scalar,DIM,DIM> Rm,Tm;
  40. if (includeReflections)
  41. polar_dec(S,Rm,Tm);
  42. else
  43. polar_svd(S,Rm,Tm);
  44. // Translation
  45. Matrix<Scalar,DIM,1> t = Ymean - scale*Rm*Xmean;
  46. // Combine
  47. T = Translation<Scalar,DIM>(t) * Rm.transpose() * Scaling(scale);
  48. }