polar_dec.cpp 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. #include "polar_dec.h"
  2. #include <Eigen/Eigenvalues>
  3. #include "polar_svd.h"
  4. #ifdef _WIN32
  5. #else
  6. # include <fenv.h>
  7. #endif
  8. // You will need the development version of Eigen which is > 3.0.3
  9. // You can determine if you have computeDirect by issuing
  10. // grep -r computeDirect path/to/eigen/*
  11. #define EIGEN_HAS_COMPUTE_DIRECT
  12. // From Olga's CGAL mentee's ARAP code
  13. template<typename Mat>
  14. IGL_INLINE void igl::polar_dec(const Mat& A, Mat& R, Mat& T)
  15. {
  16. #ifdef EIGEN_HAS_COMPUTE_DIRECT
  17. typedef typename Mat::Scalar Scalar;
  18. typedef Eigen::Matrix<typename Mat::Scalar,3,1> Vec;
  19. const Scalar th = std::sqrt(Eigen::NumTraits<Scalar>::dummy_precision());
  20. Eigen::SelfAdjointEigenSolver<Mat> eig;
  21. feclearexcept(FE_UNDERFLOW);
  22. eig.computeDirect(A.transpose()*A);
  23. if(fetestexcept(FE_UNDERFLOW) || eig.eigenvalues()(0)/eig.eigenvalues()(2)<th)
  24. return polar_svd(A,R,T);
  25. Vec S = eig.eigenvalues().cwiseSqrt();
  26. T = eig.eigenvectors() * S.asDiagonal() * eig.eigenvectors().transpose();
  27. R = A * eig.eigenvectors() * S.asDiagonal().inverse()
  28. * eig.eigenvectors().transpose();
  29. if(std::abs(R.squaredNorm()-3.) > th)
  30. return polar_svd(A,R,T);
  31. #else
  32. return polar_svd(A,R,T);
  33. #endif
  34. }
  35. #ifndef IGL_HEADER_ONLY
  36. // Explicit template instanciation
  37. template void igl::polar_dec<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
  38. #endif