pyvista.Transform

pyvista.Transform#

class Transform(*args, **kwargs)[source]#

Describes linear transformations via a 4x4 matrix.

A Transform can be used to describe the full range of linear (also known as affine) coordinate transformations in three dimensions, which are internally represented as a 4x4 homogeneous transformation matrix.

The transformation methods (e.g. translate(), rotate(), compose()) can operate in either pre_multiply() or post_multiply() mode. In pre-multiply mode, any additional transformations will occur before any transformations represented by the current matrix. In post-multiply mode (the default), the additional transformation will occur after any transformations represented by the current matrix.

Note

This class performs all of its operations in a right-handed coordinate system with right-handed rotations. Some other graphics libraries use left-handed coordinate systems and rotations.

Added in version 0.45.

Parameters:
transTransformLike | Sequence[TransformLike], optional

Initialize the transform with a transformation or sequence of transformations. By default, the transform is initialized as the identity matrix.

pointVectorLike[float], optional

Point to use when composing transformations. If set, two additional transformations are composed and added to the matrix_list:

By default, this value is None, which means that the scale, rotation, etc. transformations are performed about the origin (0, 0, 0).

multiply_mode‘pre’ | ‘post’, optional

Multiplication mode to use when composing. Set this to 'pre' for pre-multiplication or 'post' for post-multiplication.

See also

pyvista.DataObjectFilters.transform

Apply a transformation to a mesh.

pyvista.Prop3D.transform

Transform an actor.

Examples

Create a transformation and use + to compose a translation.

>>> import numpy as np
>>> import pyvista as pv
>>> position = (-0.6, -0.8, 2.1)
>>> translation_T = pv.Transform() + position
>>> translation_T.matrix
array([[ 1. ,  0. ,  0. , -0.6],
       [ 0. ,  1. ,  0. , -0.8],
       [ 0. ,  0. ,  1. ,  2.1],
       [ 0. ,  0. ,  0. ,  1. ]])

Using + performs the same concatenation as calling translate().

>>> np.array_equal(
...     translation_T.matrix, pv.Transform().translate(position).matrix
... )
True

Create a transformation and use * to compose a scaling matrix.

>>> scale_factor = 2.0
>>> scaling_T = pv.Transform() * scale_factor
>>> scaling_T.matrix
array([[2., 0., 0., 0.],
       [0., 2., 0., 0.],
       [0., 0., 2., 0.],
       [0., 0., 0., 1.]])

Using * performs the same concatenation as calling scale().

>>> np.array_equal(scaling_T.matrix, pv.Transform().scale(scale_factor).matrix)
True

Compose the two transformations using *. This will compose with post-multiplication such that the transformations are applied in order from left to right, i.e. translate first, then scale.

>>> transform_post = translation_T * scaling_T
>>> transform_post.matrix
array([[ 2. ,  0. ,  0. , -1.2],
       [ 0. ,  2. ,  0. , -1.6],
       [ 0. ,  0. ,  2. ,  4.2],
       [ 0. ,  0. ,  0. ,  1. ]])

Post-multiplication is equivalent to using matrix multiplication on the arrays directly but with the arguments reversed:

>>> mat_mul = scaling_T.matrix @ translation_T.matrix
>>> np.array_equal(transform_post.matrix, mat_mul)
True

Alternatively, compose the transformations by chaining the methods with a single Transform instance. Note that post-multiply is used by default.

>>> transform_post = pv.Transform()
>>> transform_post.multiply_mode
'post'
>>> _ = transform_post.translate(position).scale(scale_factor)
>>> transform_post.matrix
array([[ 2. ,  0. ,  0. , -1.2],
       [ 0. ,  2. ,  0. , -1.6],
       [ 0. ,  0. ,  2. ,  4.2],
       [ 0. ,  0. ,  0. ,  1. ]])

Use n_transformations to check that there are two transformations.

>>> transform_post.n_transformations
2

Use matrix_list to get a list of the transformations. Since post-multiplication is used, the translation matrix is first in the list since it was applied first, and the scale matrix is second.

>>> transform_post.matrix_list[0]  # translation
array([[ 1. ,  0. ,  0. , -0.6],
       [ 0. ,  1. ,  0. , -0.8],
       [ 0. ,  0. ,  1. ,  2.1],
       [ 0. ,  0. ,  0. ,  1. ]])
>>> transform_post.matrix_list[1]  # scaling
array([[2., 0., 0., 0.],
       [0., 2., 0., 0.],
       [0., 0., 2., 0.],
       [0., 0., 0., 1.]])

Create a similar transform but use pre-multiplication this time. Compose the transformations in the same order as before using translate() and scale().

>>> transform_pre = pv.Transform().pre_multiply()
>>> _ = transform_pre.translate(position).scale(scale_factor)

This is equivalent to using matrix multiplication directly on the arrays:

>>> mat_mul = translation_T.matrix @ scaling_T.matrix
>>> np.array_equal(transform_pre.matrix, mat_mul)
True

Show the matrix list again. Note how the order with pre-multiplication is the reverse of post-multiplication.

>>> transform_pre.matrix_list[0]  # scaling
array([[2., 0., 0., 0.],
       [0., 2., 0., 0.],
       [0., 0., 2., 0.],
       [0., 0., 0., 1.]])
>>> transform_pre.matrix_list[1]  # translation
array([[ 1. ,  0. ,  0. , -0.6],
       [ 0. ,  1. ,  0. , -0.8],
       [ 0. ,  0. ,  1. ,  2.1],
       [ 0. ,  0. ,  0. ,  1. ]])

Apply the two post- and pre-multiplied transformations to a dataset and plot them. Note how the meshes have different positions since post- and pre-multiplication produce different transformations.

>>> mesh_post = pv.Sphere().transform(transform_post, inplace=False)
>>> mesh_pre = pv.Cone().transform(transform_pre, inplace=False)
>>> pl = pv.Plotter()
>>> _ = pl.add_mesh(mesh_post, color='goldenrod')
>>> _ = pl.add_mesh(mesh_pre, color='teal')
>>> _ = pl.add_axes_at_origin()
>>> pl.show()
../../../_images/pyvista-Transform-e7351acfaa890481_00_00.png

Get the composed inverse transformation matrix of the pre-multiplication case.

>>> inverse_matrix = transform_pre.inverse_matrix
>>> inverse_matrix
array([[ 0.5 ,  0.  ,  0.  ,  0.3 ],
       [ 0.  ,  0.5 ,  0.  ,  0.4 ],
       [ 0.  ,  0.  ,  0.5 , -1.05],
       [ 0.  ,  0.  ,  0.  ,  1.  ]])

Similar to using matrix_list, we can inspect the individual transformation inverses with inverse_matrix_list.

>>> transform_pre.inverse_matrix_list[0]  # inverse scaling
array([[0.5, 0. , 0. , 0. ],
       [0. , 0.5, 0. , 0. ],
       [0. , 0. , 0.5, 0. ],
       [0. , 0. , 0. , 1. ]])
>>> transform_pre.inverse_matrix_list[1]  # inverse translation
array([[ 1. ,  0. ,  0. ,  0.6],
       [ 0. ,  1. ,  0. ,  0.8],
       [ 0. ,  0. ,  1. , -2.1],
       [ 0. ,  0. ,  0. ,  1. ]])

Transform the mesh by its inverse to restore it to its original un-scaled state and positioning at the origin.

>>> mesh_pre_inverted = mesh_pre.transform(inverse_matrix, inplace=False)
>>> pl = pv.Plotter()
>>> _ = pl.add_mesh(mesh_pre_inverted, color='teal')
>>> _ = pl.add_axes_at_origin()
>>> pl.show()
../../../_images/pyvista-Transform-e7351acfaa890481_01_00.png

Methods#

Transform.apply(obj, /[, mode, inverse, copy])

Apply the current transformation matrix to points, vectors, a dataset, or actor.

Transform.apply_to_actor(actor, /[, mode, ...])

Apply the current transformation matrix to an actor.

Transform.apply_to_dataset(dataset, /[, ...])

Apply the current transformation matrix to a dataset.

Transform.apply_to_points(points, /, *[, ...])

Apply the current transformation matrix to a point or points.

Transform.apply_to_vectors(vectors, /, *[, ...])

Apply the current transformation matrix to a vector or vectors.

Transform.as_rotation([representation])

Return the rotation component as a SciPy Rotation or any of its representations.

Transform.compose(transform, *[, point, ...])

Compose a transformation matrix.

Transform.copy()

Return a deep copy of the transform.

Transform.decompose(*[, homogeneous])

Decompose the current transformation into its components.

Transform.flip_x(*[, point, multiply_mode])

Compose a reflection about the x-axis.

Transform.flip_y(*[, point, multiply_mode])

Compose a reflection about the y-axis.

Transform.flip_z(*[, point, multiply_mode])

Compose a reflection about the z-axis.

Transform.identity()

Set the transformation to the identity transformation.

Transform.invert()

Invert the current transformation.

Transform.post_multiply()

Set the multiplication mode to post-multiply.

Transform.pre_multiply()

Set the multiplication mode to pre-multiply.

Transform.reflect(*normal[, point, ...])

Compose a reflection matrix.

Transform.rotate(rotation, *[, point, ...])

Compose a rotation matrix.

Transform.rotate_vector(vector, angle, *[, ...])

Compose a rotation about a vector.

Transform.rotate_x(angle, *[, point, ...])

Compose a rotation about the x-axis.

Transform.rotate_y(angle, *[, point, ...])

Compose a rotation about the y-axis.

Transform.rotate_z(angle, *[, point, ...])

Compose a rotation about the z-axis.

Transform.scale(*factor[, point, multiply_mode])

Compose a scale matrix.

Transform.translate(*vector[, multiply_mode])

Compose a translation matrix.

Attributes#

Transform.check_finite

Check that the matrix and inverse_matrix have finite values.

Transform.has_reflection

Return True if the current transformation matrix has a reflection component.

Transform.has_rotation

Return True if the current transformation matrix has a rotation component.

Transform.has_scale

Return True if the current transformation matrix has a scale component.

Transform.has_shear

Return True if the current transformation matrix has a shear component.

Transform.has_translation

Return True if the current transformation matrix has a translation component.

Transform.inverse_matrix

Return the inverse of the current transformation matrix.

Transform.inverse_matrix_list

Return a list of all inverse transformations applied by this Transform.

Transform.is_inverted

Get the inverse flag of the transformation.

Transform.matrix

Return or set the current transformation matrix.

Transform.matrix_list

Return a list of all current transformation matrices.

Transform.multiply_mode

Set or get the multiplication mode.

Transform.n_transformations

Return the current number of composed transformations.

Transform.point

Point to use when composing some transformations such as scale, rotation, etc.

Transform.reflection

Return the reflection component of the current transformation matrix as an integer.

Transform.rotation_axis_angle

Return the rotation component of the current transformation matrix as a vector and angle.

Transform.rotation_matrix

Return the rotation component of the current transformation matrix as a 3x3 matrix.

Transform.scale_factors

Return the scaling component of the current transformation matrix.

Transform.shear_matrix

Return the shear component of the current transformation matrix as a 3x3 matrix.

Transform.translation

Return the translation component of the current transformation matrix.