/** * @brief Compute the inverse of a matrix * * This method will compute the inverse of an affine matrix for purposes of * forward and inverse Affine computations. * * @param a Matrix to invert * * @return Affine::AMatrix The inverted matrix */ Affine::AMatrix Affine::invert(const AMatrix &a) const throw (iException &) { // Now compute the inverse affine matrix using singular value // decomposition A = USV'. So invA = V invS U'. Where ' represents // the transpose of a matrix and invS is S with the recipricol of the // diagonal elements JAMA::SVD<double> svd(a); AMatrix V; svd.getV(V); // The inverse of S is 1 over each diagonal element of S AMatrix invS; svd.getS(invS); for (int i=0; i<invS.dim1(); i++) { if (invS[i][i] == 0.0) { string msg = "Affine transform not invertible"; throw iException::Message(iException::Math,msg,_FILEINFO_); } invS[i][i] = 1.0 / invS[i][i]; } // Transpose U AMatrix U; svd.getU(U); AMatrix transU(U.dim2(),U.dim1()); for (int r=0; r<U.dim1(); r++) { for (int c=0; c<U.dim2(); c++) { transU[c][r] = U[r][c]; } } // Multiply stuff together to get the inverse of the affine AMatrix VinvS = TNT::matmult(V,invS); return (TNT::matmult(VinvS,transU)); }
/** * @brief Checks affine matrix to ensure it is a 3x3 standard form transform * * @param am Affine matrix to validate */ void Affine::checkDims(const AMatrix &am) const throw (iException &) { if ((am.dim1() != 3) && (am.dim2() != 3)) { ostringstream mess; mess << "Affine matrices must be 3x3 - this one is " << am.dim1() << "x" << am.dim2(); throw iException::Message(iException::Programmer, mess.str(), _FILEINFO_); } return; }