// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2014 Stefan Brugger // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "procrustes.h" #include "polar_dec.h" template < typename DerivedX, typename DerivedY, typename Scalar, typename DerivedR, typename DerivedT> IGL_INLINE void igl::procrustes( const Eigen::MatrixBase& X, const Eigen::MatrixBase& Y, const bool includeScaling, const bool includeReflections, Scalar& scale, Eigen::PlainObjectBase& R, Eigen::PlainObjectBase& t) { using namespace Eigen; assert (X.rows() == Y.rows() && "Same number of points"); assert(X.cols() == Y.cols() && "Points have same dimensions"); // Center data const Matrix Xmean = X.colwise().mean(); const Matrix Ymean = Y.colwise().mean(); Matrix XC = X.rowwise() - Xmean.transpose(); Matrix YC = Y.rowwise() - Ymean.transpose(); // Rotation Matrix S = XC.transpose() * YC; Matrix T; polar_dec(S, includeReflections, R, T); // Scale scale = 1.; if (includeScaling) { scale = (R.transpose() * S).trace() / (XC.array() * XC.array()).sum(); } // Translation t = Ymean - scale*R.transpose()*Xmean; } template < typename DerivedX, typename DerivedY, typename Scalar, int DIM, int TType> IGL_INLINE void igl::procrustes( const Eigen::MatrixBase& X, const Eigen::MatrixBase& Y, const bool includeScaling, const bool includeReflections, Eigen::Transform& T) { using namespace Eigen; double scale; MatrixXd R; VectorXd t; procrustes(X,Y,includeScaling,includeReflections,scale,R,t); // Combine T = Translation(t) * R * Scaling(scale); } template < typename DerivedX, typename DerivedY, typename DerivedR, typename DerivedT> IGL_INLINE void igl::procrustes( const Eigen::MatrixBase& X, const Eigen::MatrixBase& Y, const bool includeScaling, const bool includeReflections, Eigen::PlainObjectBase& S, Eigen::PlainObjectBase& t) { double scale; procrustes(X,Y,includeScaling,includeReflections,scale,S,t); S *= scale; } template < typename DerivedX, typename DerivedY, typename DerivedR, typename DerivedT> IGL_INLINE void igl::procrustes( const Eigen::MatrixBase& X, const Eigen::MatrixBase& Y, Eigen::PlainObjectBase& R, Eigen::PlainObjectBase& t) { procrustes(X,Y,false,false,R,t); } template < typename DerivedX, typename DerivedY, typename Scalar, typename DerivedT> IGL_INLINE void igl::procrustes( const Eigen::MatrixBase& X, const Eigen::MatrixBase& Y, Eigen::Rotation2D& R, Eigen::PlainObjectBase& t) { using namespace Eigen; assert (X.cols() == 2 && Y.cols() == 2 && "Points must have dimension 2"); Matrix2d Rmat; procrustes(X,Y,false,false,Rmat,t); R.fromRotationMatrix(Rmat); } #ifdef IGL_STATIC_LIBRARY template void igl::procrustes, Eigen::Matrix, double, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, const bool, const bool, double&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::procrustes, Eigen::Matrix, double, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, const bool, const bool, double&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif