affines¶
Compose and decompose homogenous affine - usually 4x4 - matrices
| 
 | Compose translations, rotations, zooms, [shears] to affine | 
| 
 | Decompose homogenous affine transformation matrix A into parts. | 
| 
 | Decompose 4x4 homogenous affine matrix into parts. | 
compose¶
- 
transforms3d.affines.compose(T, R, Z, S=None)¶
- Compose translations, rotations, zooms, [shears] to affine - Parameters
- Tarray-like shape (N,)
- Translations, where N is usually 3 (3D case) 
- Rarray-like shape (N,N)
- Rotation matrix where N is usually 3 (3D case) 
- Zarray-like shape (N,)
- Zooms, where N is usually 3 (3D case) 
- Sarray-like, shape (P,), optional
- Shear vector, such that shears fill upper triangle above diagonal to form shear matrix. P is the (N-2)th Triangular number, which happens to be 3 for a 4x4 affine (3D case) 
 
- Returns
- Aarray, shape (N+1, N+1)
- Affine transformation matrix where N usually == 3 (3D case) 
 
 - Examples - >>> T = [20, 30, 40] # translations >>> R = [[0, -1, 0], [1, 0, 0], [0, 0, 1]] # rotation matrix >>> Z = [2.0, 3.0, 4.0] # zooms >>> A = compose(T, R, Z) >>> A array([[ 0., -3., 0., 20.], [ 2., 0., 0., 30.], [ 0., 0., 4., 40.], [ 0., 0., 0., 1.]]) >>> S = np.zeros(3) >>> B = compose(T, R, Z, S) >>> np.all(A == B) True - A null set - >>> compose(np.zeros(3), np.eye(3), np.ones(3), np.zeros(3)) array([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.]]) 
decompose¶
- 
transforms3d.affines.decompose(A)¶
- Decompose homogenous affine transformation matrix A into parts. - The parts are translations, rotations, zooms, shears. - A can be any square matrix, but is typically shape (4,4). - Decomposes A into - T, R, Z, S, such that, if A is shape (4,4):- Smat = np.array([[1, S[0], S[1]], [0, 1, S[2]], [0, 0, 1]]) RZS = np.dot(R, np.dot(np.diag(Z), Smat)) A = np.eye(4) A[:3,:3] = RZS A[:-1,-1] = T - The order of transformations is therefore shears, followed by zooms, followed by rotations, followed by translations. - The case above (A.shape == (4,4)) is the most common, and corresponds to a 3D affine, but in fact A need only be square. - Parameters
- Aarray shape (N,N)
 
- Returns
- Tarray, shape (N-1,)
- Translation vector 
- Rarray shape (N-1, N-1)
- rotation matrix 
- Zarray, shape (N-1,)
- Zoom vector. May have one negative zoom to prevent need for negative determinant R matrix above 
- Sarray, shape (P,)
- Shear vector, such that shears fill upper triangle above diagonal to form shear matrix. P is the (N-2)th Triangular number, which happens to be 3 for a 4x4 affine. 
 
 - Notes - We have used a nice trick from SPM to get the shears. Let us call the starting N-1 by N-1 matrix - RZS, because it is the composition of the rotations on the zooms on the shears. The rotation matrix- Rmust have the property- np.dot(R.T, R) == np.eye(N-1). Thus- np.dot(RZS.T, RZS)will, by the transpose rules, be equal to- np.dot((ZS).T, (ZS)). Because we are doing shears with the upper right part of the matrix, that means that the Cholesky decomposition of- np.dot(RZS.T, RZS)will give us our- ZSmatrix, from which we take the zooms from the diagonal, and the shear values from the off-diagonal elements.- Examples - >>> T = [20, 30, 40] # translations >>> R = [[0, -1, 0], [1, 0, 0], [0, 0, 1]] # rotation matrix >>> Z = [2.0, 3.0, 4.0] # zooms >>> S = [0.2, 0.1, 0.3] # shears >>> # Now we make an affine matrix >>> A = np.eye(4) >>> Smat = np.array([[1, S[0], S[1]], ... [0, 1, S[2]], ... [0, 0, 1]]) >>> RZS = np.dot(R, np.dot(np.diag(Z), Smat)) >>> A[:3,:3] = RZS >>> A[:-1,-1] = T # set translations >>> Tdash, Rdash, Zdash, Sdash = decompose(A) >>> np.allclose(T, Tdash) True >>> np.allclose(R, Rdash) True >>> np.allclose(Z, Zdash) True >>> np.allclose(S, Sdash) True 
decompose44¶
- 
transforms3d.affines.decompose44(A44)¶
- Decompose 4x4 homogenous affine matrix into parts. - The parts are translations, rotations, zooms, shears. - This is the same as - decompose()but specialized for 4x4 affines.- Decomposes A44 into - T, R, Z, S, such that:- Smat = np.array([[1, S[0], S[1]], [0, 1, S[2]], [0, 0, 1]]) RZS = np.dot(R, np.dot(np.diag(Z), Smat)) A44 = np.eye(4) A44[:3,:3] = RZS A44[:-1,-1] = T - The order of transformations is therefore shears, followed by zooms, followed by rotations, followed by translations. - This routine only works for shape (4,4) matrices - Parameters
- A44array shape (4,4)
 
- Returns
- Tarray, shape (3,)
- Translation vector 
- Rarray shape (3,3)
- rotation matrix 
- Zarray, shape (3,)
- Zoom vector. May have one negative zoom to prevent need for negative determinant R matrix above 
- Sarray, shape (3,)
- Shear vector, such that shears fill upper triangle above diagonal to form shear matrix (type - striu).
 
 - Notes - The implementation inspired by: - Decomposing a matrix into simple transformations by Spencer W. Thomas, pp 320-323 in Graphics Gems II, James Arvo (editor), Academic Press, 1991, ISBN: 0120644819. - The upper left 3x3 of the affine consists of a matrix we’ll call RZS: - RZS = R * Z *S - where R is a rotation matrix, Z is a diagonal matrix of scalings: - Z = diag([sx, sy, sz]) - and S is a shear matrix of form: - S = [[1, sxy, sxz], [0, 1, syz], [0, 0, 1]]) - Running all this through sympy (see ‘derivations’ folder) gives - RZSas- [R00*sx, R01*sy + R00*sx*sxy, R02*sz + R00*sx*sxz + R01*sy*syz] [R10*sx, R11*sy + R10*sx*sxy, R12*sz + R10*sx*sxz + R11*sy*syz] [R20*sx, R21*sy + R20*sx*sxy, R22*sz + R20*sx*sxz + R21*sy*syz] - Ris defined as being a rotation matrix, so the dot products between the columns of- Rare zero, and the norm of each column is 1. Thus the dot product:- R[:,0].T * RZS[:,1] - that results in: - [R00*R01*sy + R10*R11*sy + R20*R21*sy + sx*sxy*R00**2 + sx*sxy*R10**2 + sx*sxy*R20**2] - simplifies to - sy*0 + sx*sxy*1==- sx*sxy. Therefore:- R[:,1] * sy = RZS[:,1] - R[:,0] * (R[:,0].T * RZS[:,1]) - allowing us to get - sywith the norm, and sxy with- R[:,0].T * RZS[:,1] / sx.- Similarly - R[:,0].T * RZS[:,2]simplifies to- sx*sxz, and- R[:,1].T * RZS[:,2]to- sy*syzgiving us the remaining unknowns.- Examples - >>> T = [20, 30, 40] # translations >>> R = [[0, -1, 0], [1, 0, 0], [0, 0, 1]] # rotation matrix >>> Z = [2.0, 3.0, 4.0] # zooms >>> S = [0.2, 0.1, 0.3] # shears >>> # Now we make an affine matrix >>> A = np.eye(4) >>> Smat = np.array([[1, S[0], S[1]], ... [0, 1, S[2]], ... [0, 0, 1]]) >>> RZS = np.dot(R, np.dot(np.diag(Z), Smat)) >>> A[:3,:3] = RZS >>> A[:-1,-1] = T # set translations >>> Tdash, Rdash, Zdash, Sdash = decompose44(A) >>> np.allclose(T, Tdash) True >>> np.allclose(R, Rdash) True >>> np.allclose(Z, Zdash) True >>> np.allclose(S, Sdash) True