c++ - How do I invert an affine transformation with translation, rotation, and scaling? -
i have 4x4 matrix translation, rotation, , scaling components, no shear or other transformations. how find inverse? i'm using eigen library in c++.
this tricky right, since operations need performed in correct order:
template<class derived> matrix4f affineinverse(const eigen::matrixbase<derived>& mat) { matrix3f rotsclinv = ( mat.block<3, 3>(0, 0).array().rowwise() / mat.block<3, 3>(0, 0).colwise().squarednorm().array() //scaling ).transpose(); //rotation return (matrix4f(4,4) << rotsclinv , -rotsclinv * mat.block<3, 1>(0, 3) //translation , 0, 0, 0, 1).finished(); }
as this answer states, inverse of top left 3x3 block can calculated separately:
inv ([ b ]) = [inv(a) -inv(a)*b] ([ 0 1 ]) [ 0 1 ]
the key insight top left block scaling , rotation equal orthogonal (rotation) matrix q
times diagonal (scaling) matrix d
: q*d
. invert it, linear algebra:
inv(q*d) = transp(transp(inv(q*d))) = transp(inv(transp(q*d))) = transp(inv(transp(d)*transp(q)))
(see this proof), , since d
diagonal , q
orthogonal,
= transp(inv(d*inv(q))) = transp(q*inv(d))).
q*inv(d)
easy find: since in q*d
each column column of q
(which unit vector) times entry of d
(which scalar), enough divide each column square of norm. first 3 lines of function do.
written out in linear algebra form:
inv ([ q*d b ]) = [transp(q*inv(d)) -transp(q*inv(d))*b] ([ 0 1 ]) [ 0 1 ]
Comments
Post a Comment