#pragma once #include #include #include #include #include namespace cgv { namespace math { ///polar decomposition of matrix c=r*a ///r orthonormal matrix ///a positive semi-definite matrix template void polar(const mat &c, mat &r, mat &a,int num_iter=15) { r = c; for(int i =0; i < num_iter;i++) r = ((T)0.5)*(r+transpose(inv(r))); a = inv(r)*c; /* * Alternative way using svd: * c = u*d*v^t * r = u*v^t, a=v*d*v^t */ } /// extract axis and angle from rotation matrix ///returns true if successful problematic cases are angle == 0° and angle == 180° template bool decompose_rotation(const cgv::math::mat& R, cgv::math::vec& axis, T& angle) { assert(R.nrows() == 3 && R.ncols() == 3); mat A = (T)0.5*(R - transpose(R)); mat S = (T)0.5*(R + transpose(R)); T abssina = (T)sqrt(0.5*(double)(A.frobenius_norm()*A.frobenius_norm())); T cosa = 0.5*(trace(S)-1.0); angle =(T)(asin(abssina)*180.0/PI); if(cosa < 0) angle = (T)180.0-angle; if(angle == 0 || angle == 180.0) return false; axis = (T)1.0/abssina*cgv::math::vec(A(2,1),A(0,2),A(1,0)); return true; } } }