pyvista.Transform.decompose#
- Transform.decompose(
- *,
- homogeneous: bool = False,
Decompose the current transformation into its components.
Decompose the
matrixMintotranslation
Trotation
Rreflection
Nscaling
Sshearing
K
such that, when represented as 4x4 matrices,
M = TRNSK. The decomposition is unique and is computed with polar matrix decomposition.By default, compact representations of the transformations are returned (e.g. as a 3-element vector or a 3x3 matrix). Optionally, 4x4 matrices may be returned instead.
Note
The rotation is orthonormal and right-handed with positive determinant.
The scaling factors are positive.
The reflection is either
1(no reflection) or-1(has reflection) and can be used like a scaling factor.
- Parameters:
- Returns:
numpy.ndarrayTranslation component
T. Returned as a 3-element vector (or a 4x4 translation matrix ifhomogeneousisTrue).numpy.ndarrayRotation component
R. Returned as a 3x3 orthonormal rotation matrix of row vectors (or a 4x4 rotation matrix ifhomogeneousisTrue).numpy.ndarrayReflection component
N. Returned as a NumPy scalar (or a 4x4 reflection matrix ifhomogeneousisTrue).numpy.ndarrayScaling component
S. Returned as a 3-element vector (or a 4x4 scaling matrix ifhomogeneousisTrue).numpy.ndarrayShear component
K. Returned as a 3x3 matrix with ones on the diagonal and shear values in the off-diagonals (or as a 4x4 shearing matrix ifhomogeneousisTrue).
See also
composeCompose a transformation.
as_rotationGet this transform’s rotation component.
Examples
Create a transform by composing scaling, rotation, and translation matrices.
>>> import numpy as np >>> import pyvista as pv >>> transform = pv.Transform() >>> _ = transform.scale(1, 2, 3) >>> _ = transform.rotate_z(90) >>> _ = transform.translate(4, 5, 6) >>> transform Transform (...) Num Transformations: 3 Matrix: [[ 0., -2., 0., 4.], [ 1., 0., 0., 5.], [ 0., 0., 3., 6.], [ 0., 0., 0., 1.]]
Decompose the matrix.
>>> T, R, N, S, K = transform.decompose()
Since the input has no shear this component is the identity matrix. Similarly, there are no reflections so its value is
1. All other components are recovered perfectly and match the input.>>> K # shear array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
>>> S # scale array([1., 2., 3.])
>>> N # reflection array(1.)
>>> R # rotation array([[ 0., -1., 0.], [ 1., 0., 0.], [ 0., 0., 1.]])
>>> T # translation array([4., 5., 6.])
Compose a shear component using pre-multiplication so that shearing is the first transformation.
>>> shear = np.eye(4) >>> shear[0, 1] = 0.1 # xy shear >>> _ = transform.compose(shear, multiply_mode='pre')
Repeat the decomposition and show its components. Note how the decomposed shear does not perfectly match the input shear matrix values. The values of the scaling and rotation components are also affected and do not exactly match the input. This is expected, because the shear can be partially factored as a combination of rotation and scaling.
>>> T, R, N, S, K = transform.decompose()
>>> K # shear array([[1. , 0.03333333, 0. ], [0.01663894, 1. , 0. ], [0. , 0. , 1. ]])
>>> S # scale array([0.99944491, 2.0022213 , 3. ])
>>> N # reflection array(1.)
>>> R # rotation array([[ 0.03331483, -0.99944491, 0. ], [ 0.99944491, 0.03331483, 0. ], [ 0. , 0. , 1. ]])
>>> T # translation array([4., 5., 6.])
Although the values may not match the input exactly, the decomposition is nevertheless valid and can be used to re-compose the original transformation.
>>> T, R, N, S, K = transform.decompose(homogeneous=True) >>> T @ R @ N @ S @ K array([[-5.76153045e-17, -2.00000000e+00, 0.00000000e+00, 4.00000000e+00], [ 1.00000000e+00, 1.00000000e-01, 0.00000000e+00, 5.00000000e+00], [ 0.00000000e+00, 0.00000000e+00, 3.00000000e+00, 6.00000000e+00], [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]])
Alternatively, re-compose the transformation as a new
Transformwith pre-multiplication.>>> recomposed = pv.Transform([T, R, N, S, K], multiply_mode='pre') >>> np.allclose(recomposed.matrix, transform.matrix) True
Compose a reflection and decompose the transform again.
>>> _ = transform.flip_x() >>> T, R, N, S, K = transform.decompose()
The reflection component is now
-1.>>> N # reflection array(-1.)
The decomposition may be simplified to a
TRSKdecomposition by combining the reflection component with either the rotation or the scaling term.Multiplying the reflection with the rotation will make it a left-handed rotation with negative determinant:
>>> R = R * N >>> np.linalg.det(R) < 0 np.True_
Alternatively, keep the rotation right-handed but make the scaling factors negative:
>>> S = S * N >>> S # scale array([-0.99944491, -2.0022213 , -3. ])