init
This commit is contained in:
@@ -0,0 +1,688 @@
|
||||
"""Prop3D module."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC
|
||||
from abc import abstractmethod
|
||||
from functools import wraps
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Literal
|
||||
|
||||
import numpy as np
|
||||
|
||||
from pyvista._deprecate_positional_args import _deprecate_positional_args
|
||||
from pyvista.core import _validation
|
||||
from pyvista.core._typing_core import BoundsTuple
|
||||
from pyvista.core.utilities.arrays import array_from_vtkmatrix
|
||||
from pyvista.core.utilities.arrays import vtkmatrix_from_array
|
||||
from pyvista.core.utilities.misc import _BoundsSizeMixin
|
||||
from pyvista.core.utilities.misc import _NameMixin
|
||||
from pyvista.core.utilities.misc import _NoNewAttrMixin
|
||||
from pyvista.core.utilities.transform import Transform
|
||||
from pyvista.plotting import _vtk
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import Self
|
||||
|
||||
from pyvista.core._typing_core import NumpyArray
|
||||
from pyvista.core._typing_core import RotationLike
|
||||
from pyvista.core._typing_core import TransformLike
|
||||
from pyvista.core._typing_core import VectorLike
|
||||
|
||||
|
||||
class Prop3D(
|
||||
_NoNewAttrMixin, _NameMixin, _BoundsSizeMixin, _vtk.DisableVtkSnakeCase, _vtk.vtkProp3D
|
||||
):
|
||||
"""Prop3D wrapper for :vtk:`vtkProp3D`.
|
||||
|
||||
Used to represent an entity in a rendering scene. It provides spatial
|
||||
properties and methods relating to an entity's position, orientation
|
||||
and scale. It is used as parent class for :class:`pyvista.Actor`,
|
||||
:class:`pyvista.AxesActor`, and :class:`pyvista.plotting.volume.Volume`.
|
||||
|
||||
``Prop3D`` applies transformations in the following order:
|
||||
|
||||
#. Translate entity to its :attr:`~origin`.
|
||||
#. Scale entity by the values in :attr:`~scale`.
|
||||
#. Rotate entity using the values in :attr:`~orientation`. Internally, rotations are
|
||||
applied in the order :func:`~rotate_y`, then :func:`~rotate_x`, then :func:`~rotate_z`.
|
||||
#. Translate entity away from its origin and to its :attr:`~position`.
|
||||
#. Transform entity with :attr:`~user_matrix`.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize Prop3D."""
|
||||
super().__init__()
|
||||
|
||||
@property
|
||||
def scale(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
||||
"""Return or set entity scale.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Create an actor using the :class:`pyvista.Plotter` and then change the
|
||||
scale of the actor.
|
||||
|
||||
>>> import pyvista as pv
|
||||
>>> pl = pv.Plotter()
|
||||
>>> actor = pl.add_mesh(pv.Sphere())
|
||||
>>> actor.scale = (2.0, 2.0, 2.0)
|
||||
>>> actor.scale
|
||||
(2.0, 2.0, 2.0)
|
||||
|
||||
"""
|
||||
return self.GetScale()
|
||||
|
||||
@scale.setter
|
||||
def scale(self, value: float | VectorLike[float]) -> None:
|
||||
self.SetScale(value) # type: ignore[arg-type]
|
||||
|
||||
@property
|
||||
def position(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
||||
"""Return or set the entity position.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Change the position of an actor. Note how this does not change the
|
||||
position of the underlying dataset, just the relative location of the
|
||||
actor in the :class:`pyvista.Plotter`.
|
||||
|
||||
>>> import pyvista as pv
|
||||
>>> mesh = pv.Sphere()
|
||||
>>> pl = pv.Plotter()
|
||||
>>> _ = pl.add_mesh(mesh, color='b')
|
||||
>>> actor = pl.add_mesh(mesh, color='r')
|
||||
>>> actor.position = (0, 0, 1) # shifts the red sphere up
|
||||
>>> pl.show()
|
||||
|
||||
"""
|
||||
return self.GetPosition()
|
||||
|
||||
@position.setter
|
||||
def position(self, value: VectorLike[float]) -> None:
|
||||
self.SetPosition(value) # type: ignore[call-overload]
|
||||
|
||||
def rotate_x(self, angle: float) -> None:
|
||||
"""Rotate the entity about the x-axis.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
angle : float
|
||||
Angle to rotate the entity about the x-axis in degrees.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Rotate the actor about the x-axis 45 degrees. Note how this does not
|
||||
change the location of the underlying dataset.
|
||||
|
||||
>>> import pyvista as pv
|
||||
>>> mesh = pv.Cube()
|
||||
>>> pl = pv.Plotter()
|
||||
>>> _ = pl.add_mesh(mesh, color='b')
|
||||
>>> actor = pl.add_mesh(
|
||||
... mesh,
|
||||
... color='r',
|
||||
... style='wireframe',
|
||||
... line_width=5,
|
||||
... lighting=False,
|
||||
... )
|
||||
>>> actor.rotate_x(45)
|
||||
>>> pl.show_axes()
|
||||
>>> pl.show()
|
||||
|
||||
"""
|
||||
self.RotateX(angle)
|
||||
|
||||
def rotate_y(self, angle: float) -> None:
|
||||
"""Rotate the entity about the y-axis.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
angle : float
|
||||
Angle to rotate the entity about the y-axis in degrees.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Rotate the actor about the y-axis 45 degrees. Note how this does not
|
||||
change the location of the underlying dataset.
|
||||
|
||||
>>> import pyvista as pv
|
||||
>>> mesh = pv.Cube()
|
||||
>>> pl = pv.Plotter()
|
||||
>>> _ = pl.add_mesh(mesh, color='b')
|
||||
>>> actor = pl.add_mesh(
|
||||
... mesh,
|
||||
... color='r',
|
||||
... style='wireframe',
|
||||
... line_width=5,
|
||||
... lighting=False,
|
||||
... )
|
||||
>>> actor.rotate_y(45)
|
||||
>>> pl.show_axes()
|
||||
>>> pl.show()
|
||||
|
||||
"""
|
||||
self.RotateY(angle)
|
||||
|
||||
def rotate_z(self, angle: float) -> None:
|
||||
"""Rotate the entity about the z-axis.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
angle : float
|
||||
Angle to rotate the entity about the z-axis in degrees.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Rotate the actor about the z-axis 45 degrees. Note how this does not
|
||||
change the location of the underlying dataset.
|
||||
|
||||
>>> import pyvista as pv
|
||||
>>> mesh = pv.Cube()
|
||||
>>> pl = pv.Plotter()
|
||||
>>> _ = pl.add_mesh(mesh, color='b')
|
||||
>>> actor = pl.add_mesh(
|
||||
... mesh,
|
||||
... color='r',
|
||||
... style='wireframe',
|
||||
... line_width=5,
|
||||
... lighting=False,
|
||||
... )
|
||||
>>> actor.rotate_z(45)
|
||||
>>> pl.show_axes()
|
||||
>>> pl.show()
|
||||
|
||||
"""
|
||||
self.RotateZ(angle)
|
||||
|
||||
@property
|
||||
def orientation(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
||||
"""Return or set the entity orientation angles.
|
||||
|
||||
Orientation angles of the axes which define rotations about the
|
||||
world's x-y-z axes. The angles are specified in degrees and in
|
||||
x-y-z order. However, the actual rotations are applied in the
|
||||
following order: :func:`~rotate_y` first, then :func:`~rotate_x`
|
||||
and finally :func:`~rotate_z`.
|
||||
|
||||
Rotations are applied about the specified :attr:`~origin`.
|
||||
|
||||
See Also
|
||||
--------
|
||||
rotation_from
|
||||
Alternative method for setting the :attr:`orientation`.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Reorient just the actor and plot it. Note how the actor is rotated
|
||||
about the origin ``(0, 0, 0)`` by default.
|
||||
|
||||
>>> import pyvista as pv
|
||||
>>> mesh = pv.Cube(center=(0, 0, 3))
|
||||
>>> pl = pv.Plotter()
|
||||
>>> _ = pl.add_mesh(mesh, color='b')
|
||||
>>> actor = pl.add_mesh(
|
||||
... mesh,
|
||||
... color='r',
|
||||
... style='wireframe',
|
||||
... line_width=5,
|
||||
... lighting=False,
|
||||
... )
|
||||
>>> actor.orientation = (45, 0, 0)
|
||||
>>> _ = pl.add_axes_at_origin()
|
||||
>>> pl.show()
|
||||
|
||||
Repeat the last example, but this time reorient the actor about
|
||||
its center by specifying its :attr:`~origin`.
|
||||
|
||||
>>> import pyvista as pv
|
||||
>>> mesh = pv.Cube(center=(0, 0, 3))
|
||||
>>> pl = pv.Plotter()
|
||||
>>> _ = pl.add_mesh(mesh, color='b')
|
||||
>>> actor = pl.add_mesh(
|
||||
... mesh,
|
||||
... color='r',
|
||||
... style='wireframe',
|
||||
... line_width=5,
|
||||
... lighting=False,
|
||||
... )
|
||||
>>> actor.origin = actor.center
|
||||
>>> actor.orientation = (45, 0, 0)
|
||||
>>> _ = pl.add_axes_at_origin()
|
||||
>>> pl.show()
|
||||
|
||||
Show that the orientation changes with rotation.
|
||||
|
||||
>>> import pyvista as pv
|
||||
>>> mesh = pv.Cube()
|
||||
>>> pl = pv.Plotter()
|
||||
>>> actor = pl.add_mesh(mesh)
|
||||
>>> actor.rotate_x(90)
|
||||
>>> actor.orientation # doctest:+SKIP
|
||||
(90, 0, 0)
|
||||
|
||||
Set the orientation directly.
|
||||
|
||||
>>> actor.orientation = (0, 45, 45)
|
||||
>>> actor.orientation # doctest:+SKIP
|
||||
(0, 45, 45)
|
||||
|
||||
"""
|
||||
return self.GetOrientation()
|
||||
|
||||
@orientation.setter
|
||||
def orientation(self, value: VectorLike[float]) -> None:
|
||||
self.SetOrientation(value) # type: ignore[call-overload]
|
||||
|
||||
@property
|
||||
def origin(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
||||
"""Return or set the entity origin.
|
||||
|
||||
This is the point about which all rotations take place.
|
||||
|
||||
See :attr:`~orientation` for examples.
|
||||
|
||||
"""
|
||||
return self.GetOrigin()
|
||||
|
||||
@origin.setter
|
||||
def origin(self, value: VectorLike[float]) -> None:
|
||||
self.SetOrigin(value) # type: ignore[arg-type]
|
||||
|
||||
@property
|
||||
def bounds(self) -> BoundsTuple: # numpydoc ignore=RT01
|
||||
"""Return the bounds of the entity.
|
||||
|
||||
Bounds are ``(x_min, x_max, y_min, y_max, z_min, z_max)``
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> import pyvista as pv
|
||||
>>> pl = pv.Plotter()
|
||||
>>> mesh = pv.Cube(x_length=0.1, y_length=0.2, z_length=0.3)
|
||||
>>> actor = pl.add_mesh(mesh)
|
||||
>>> actor.bounds
|
||||
BoundsTuple(x_min = -0.05,
|
||||
x_max = 0.05,
|
||||
y_min = -0.1,
|
||||
y_max = 0.1,
|
||||
z_min = -0.15,
|
||||
z_max = 0.15)
|
||||
|
||||
"""
|
||||
return BoundsTuple(*self.GetBounds())
|
||||
|
||||
@property
|
||||
def center(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
||||
"""Return the center of the entity.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> import pyvista as pv
|
||||
>>> pl = pv.Plotter()
|
||||
>>> actor = pl.add_mesh(pv.Sphere(center=(0.5, 0.5, 1)))
|
||||
>>> actor.center # doctest:+SKIP
|
||||
(0.5, 0.5, 1)
|
||||
|
||||
"""
|
||||
return self.GetCenter()
|
||||
|
||||
@property
|
||||
def user_matrix(self) -> NumpyArray[float]: # numpydoc ignore=RT01
|
||||
"""Return or set the user matrix.
|
||||
|
||||
In addition to the instance variables such as position and orientation, the user
|
||||
can add an additional transformation to the actor.
|
||||
|
||||
This matrix is concatenated with the actor's internal transformation that is
|
||||
implicitly created when the actor is created. This affects the actor/rendering
|
||||
only, not the input data itself.
|
||||
|
||||
The user matrix is the last transformation applied to the actor before
|
||||
rendering.
|
||||
|
||||
See Also
|
||||
--------
|
||||
transform
|
||||
Apply a transformation to the :attr:`user_matrix`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
np.ndarray
|
||||
A 4x4 transformation matrix.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Apply a 4x4 translation to a wireframe actor. This 4x4 transformation
|
||||
effectively translates the actor by one unit in the Z direction,
|
||||
rotates the actor about the z-axis by approximately 45 degrees, and
|
||||
shrinks the actor by a factor of 0.5.
|
||||
|
||||
>>> import pyvista as pv
|
||||
>>> mesh = pv.Cube()
|
||||
>>> pl = pv.Plotter()
|
||||
>>> _ = pl.add_mesh(mesh, color='b')
|
||||
>>> actor = pl.add_mesh(
|
||||
... mesh,
|
||||
... color='r',
|
||||
... style='wireframe',
|
||||
... line_width=5,
|
||||
... lighting=False,
|
||||
... )
|
||||
>>> arr = [
|
||||
... [0.707, -0.707, 0, 0],
|
||||
... [0.707, 0.707, 0, 0],
|
||||
... [0, 0, 1, 1.5],
|
||||
... [0, 0, 0, 2],
|
||||
... ]
|
||||
>>> actor.user_matrix = arr
|
||||
>>> pl.show_axes()
|
||||
>>> pl.show()
|
||||
|
||||
"""
|
||||
if self.GetUserMatrix() is None:
|
||||
self.SetUserMatrix(vtkmatrix_from_array(np.eye(4)))
|
||||
return array_from_vtkmatrix(self.GetUserMatrix())
|
||||
|
||||
@user_matrix.setter
|
||||
def user_matrix(self, value: TransformLike) -> None:
|
||||
array = np.eye(4) if value is None else _validation.validate_transform4x4(value)
|
||||
self.SetUserMatrix(vtkmatrix_from_array(array))
|
||||
|
||||
def transform(
|
||||
self,
|
||||
trans: TransformLike,
|
||||
multiply_mode: Literal['pre', 'post'] = 'post',
|
||||
*,
|
||||
inplace: bool = False,
|
||||
):
|
||||
"""Apply a transformation to this object's :attr:`user_matrix`.
|
||||
|
||||
.. note::
|
||||
|
||||
This applies a transformation by modifying the :attr:`user_matrix`. This
|
||||
differs from methods like :meth:`rotate_x`, :meth:`rotate_y`, :meth:`rotate_z`,
|
||||
and :meth:`rotation_from` which apply a transformation indirectly by modifying
|
||||
the :attr:`orientation`. See the :class:`Prop3D` class description for more
|
||||
information about how this class is transformed.
|
||||
|
||||
.. versionadded:: 0.45
|
||||
|
||||
Parameters
|
||||
----------
|
||||
trans : TransformLike
|
||||
Transformation matrix as a 3x3 or 4x4 array, :vtk:`vtkMatrix3x3` or
|
||||
:vtk:`vtkMatrix4x4`, :vtk:`vtkTransform`, or a SciPy ``Rotation`` instance.
|
||||
If the input is 3x3, the array is padded using a 4x4 identity matrix.
|
||||
|
||||
multiply_mode : 'pre' | 'post', default: 'post'
|
||||
Multiplication mode to use.
|
||||
|
||||
- ``'pre'``: pre-multiply ``trans`` with the :attr:`user_matrix`, i.e.
|
||||
``user_matrix @ trans``. The transformation is applied `before` the
|
||||
current user-matrix.
|
||||
- ``'post'``: post-multiply ``trans`` with the :attr:`user_matrix`, i.e.
|
||||
``trans @ user_matrix``. The transformation is applied `after` the
|
||||
current user-matrix.
|
||||
|
||||
inplace : bool, default: False
|
||||
When ``True``, modifies the prop inplace. Otherwise, a copy is returned.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Prop3D
|
||||
Transformed prop.
|
||||
|
||||
See Also
|
||||
--------
|
||||
pyvista.Transform
|
||||
Describe linear transformations via a 4x4 matrix.
|
||||
pyvista.DataObjectFilters.transform
|
||||
Apply a transformation to a mesh.
|
||||
|
||||
"""
|
||||
# Validate input
|
||||
_validation.check_contains(
|
||||
['pre', 'post'], must_contain=multiply_mode, name='multiply_mode'
|
||||
)
|
||||
matrix = _validation.validate_transform4x4(trans)
|
||||
|
||||
# Update user matrix
|
||||
new_matrix = (
|
||||
self.user_matrix @ matrix if multiply_mode == 'pre' else matrix @ self.user_matrix
|
||||
)
|
||||
output = self if inplace else self.copy()
|
||||
output.user_matrix = new_matrix
|
||||
return output
|
||||
|
||||
@abstractmethod
|
||||
@_deprecate_positional_args
|
||||
def copy(
|
||||
self: Self,
|
||||
deep: bool = True, # noqa: FBT001, FBT002
|
||||
) -> Self: # numpydoc ignore=RT01
|
||||
"""Return a copy of this prop."""
|
||||
raise NotImplementedError # pragma: no cover
|
||||
|
||||
@property
|
||||
def length(self) -> float: # numpydoc ignore=RT01
|
||||
"""Return the length of the entity.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> import pyvista as pv
|
||||
>>> pl = pv.Plotter()
|
||||
>>> actor = pl.add_mesh(pv.Sphere())
|
||||
>>> actor.length
|
||||
1.7272069317100354
|
||||
|
||||
"""
|
||||
return self.GetLength()
|
||||
|
||||
def rotation_from(self, rotation: RotationLike) -> None:
|
||||
"""Set the entity's orientation from a rotation.
|
||||
|
||||
Set the rotation of this entity from a 3x3 rotation matrix. This includes
|
||||
NumPy arrays, a :vtk:`vtkMatrix3x3`, and SciPy ``Rotation`` objects.
|
||||
|
||||
This method may be used as an alternative for setting the :attr:`orientation`.
|
||||
|
||||
.. versionadded:: 0.45
|
||||
|
||||
Parameters
|
||||
----------
|
||||
rotation : RotationLike
|
||||
3x3 rotation matrix or a SciPy ``Rotation`` object.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Create an actor and show its initial orientation.
|
||||
|
||||
>>> import pyvista as pv
|
||||
>>> pl = pv.Plotter()
|
||||
>>> actor = pl.add_mesh(pv.Sphere())
|
||||
>>> actor.orientation
|
||||
(0.0, -0.0, 0.0)
|
||||
|
||||
Set the orientation using a 3x3 matrix.
|
||||
|
||||
>>> actor.rotation_from([[0, 1, 0], [1, 0, 0], [0, 0, 1]])
|
||||
>>> actor.orientation
|
||||
(0.0, -180.0, -89.99999999999999)
|
||||
|
||||
"""
|
||||
self.orientation = _rotation_matrix_as_orientation(rotation) # type: ignore[arg-type]
|
||||
|
||||
|
||||
def _rotation_matrix_as_orientation(
|
||||
array: NumpyArray[float] | _vtk.vtkMatrix3x3,
|
||||
) -> tuple[float, float, float]:
|
||||
"""Convert a 3x3 rotation matrix to x-y-z orientation angles.
|
||||
|
||||
The orientation angles define rotations about the world's x-y-z axes. The angles
|
||||
are specified in degrees and in x-y-z order. However, the rotations should
|
||||
be applied in the order: first rotate about the y-axis, then x-axis, then z-axis.
|
||||
|
||||
The rotation angles and rotation matrix can be used interchangeably for
|
||||
transformations.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
array : NumpyArray[float] | :vtk:`vtkMatrix3x3`
|
||||
3x3 rotation matrix as a NumPy array or a :vtk:`vtkMatrix3x3`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple
|
||||
Tuple with x-y-z axis rotation angles in degrees.
|
||||
|
||||
"""
|
||||
return Transform().rotate(array).GetOrientation()
|
||||
|
||||
|
||||
def _orientation_as_rotation_matrix(orientation: VectorLike[float]) -> NumpyArray[float]:
|
||||
"""Convert x-y-z orientation angles to a 3x3 matrix.
|
||||
|
||||
The orientation angles define rotations about the world's x-y-z axes. The angles
|
||||
are specified in degrees and in x-y-z order. However, the rotations should
|
||||
be applied in the order: first rotate about the y-axis, then x-axis, then z-axis.
|
||||
|
||||
The rotation angles and rotation matrix can be used interchangeably for
|
||||
transformations.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
orientation : VectorLike[float]
|
||||
The x-y-z axis orientation angles in degrees.
|
||||
|
||||
Returns
|
||||
-------
|
||||
numpy.ndarray
|
||||
3x3 rotation matrix.
|
||||
|
||||
"""
|
||||
valid_orientation = _validation.validate_array3(orientation, name='orientation')
|
||||
prop = _vtk.vtkActor()
|
||||
prop.SetOrientation(valid_orientation)
|
||||
matrix = _vtk.vtkMatrix4x4()
|
||||
prop.GetMatrix(matrix)
|
||||
return array_from_vtkmatrix(matrix)[:3, :3]
|
||||
|
||||
|
||||
class _Prop3DMixin(_BoundsSizeMixin, ABC):
|
||||
"""Add 3D transformations to props which do not inherit from :class:`pyvista.Prop3D`.
|
||||
|
||||
Derived classes need to implement the :meth:`_post_set_update` method to define
|
||||
their behavior, e.g. manually apply a transformation.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
from pyvista import Actor # Avoid circular import # noqa: PLC0415
|
||||
|
||||
self._prop3d = Actor()
|
||||
|
||||
@property
|
||||
@wraps(Prop3D.scale.fget) # type: ignore[attr-defined]
|
||||
def scale(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
||||
"""Wrap :class:`pyvista.Prop3D.scale."""
|
||||
return self._prop3d.scale
|
||||
|
||||
@scale.setter
|
||||
@wraps(Prop3D.scale.fset) # type: ignore[attr-defined]
|
||||
def scale(self, scale: VectorLike[float]) -> None:
|
||||
self._prop3d.scale = scale
|
||||
self._post_set_update()
|
||||
|
||||
@property
|
||||
@wraps(Prop3D.position.fget) # type: ignore[attr-defined]
|
||||
def position(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
||||
"""Wrap :class:`pyvista.Prop3D.position."""
|
||||
return self._prop3d.position
|
||||
|
||||
@position.setter
|
||||
@wraps(Prop3D.position.fset) # type: ignore[attr-defined]
|
||||
def position(self, position: VectorLike[float]) -> None:
|
||||
self._prop3d.position = position
|
||||
self._post_set_update()
|
||||
|
||||
@property
|
||||
@wraps(Prop3D.orientation.fget) # type: ignore[attr-defined]
|
||||
def orientation(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
||||
"""Wrap :class:`pyvista.Prop3D.orientation."""
|
||||
return self._prop3d.orientation
|
||||
|
||||
@orientation.setter
|
||||
@wraps(Prop3D.orientation.fset) # type: ignore[attr-defined]
|
||||
def orientation(self, orientation: VectorLike[float]) -> None:
|
||||
self._prop3d.orientation = orientation
|
||||
self._post_set_update()
|
||||
|
||||
@property
|
||||
@wraps(Prop3D.origin.fget) # type: ignore[attr-defined]
|
||||
def origin(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
||||
"""Wrap :class:`pyvista.Prop3D.origin."""
|
||||
return self._prop3d.origin
|
||||
|
||||
@origin.setter
|
||||
@wraps(Prop3D.origin.fset) # type: ignore[attr-defined]
|
||||
def origin(self, origin: VectorLike[float]) -> None:
|
||||
self._prop3d.origin = origin
|
||||
self._post_set_update()
|
||||
|
||||
@property
|
||||
@wraps(Prop3D.user_matrix.fget) # type: ignore[attr-defined]
|
||||
def user_matrix(self) -> NumpyArray[float]: # numpydoc ignore=RT01
|
||||
"""Wrap :class:`pyvista.Prop3D.user_matrix."""
|
||||
return self._prop3d.user_matrix
|
||||
|
||||
@user_matrix.setter
|
||||
@wraps(Prop3D.user_matrix.fset) # type: ignore[attr-defined]
|
||||
def user_matrix(self, matrix: TransformLike) -> None:
|
||||
self._prop3d.user_matrix = matrix
|
||||
self._post_set_update()
|
||||
|
||||
@property
|
||||
def _transformation_matrix(self):
|
||||
"""Transformation matrix applied to the actor.
|
||||
|
||||
The transformation is computed from the attributes :attr:`position`
|
||||
:attr:`origin`, :attr:`scale`, :attr:`orientation`, and :attr:`user_matrix`.
|
||||
|
||||
It is the actual transformation applied to the actor under-the-hood by vtk.
|
||||
"""
|
||||
return array_from_vtkmatrix(self._prop3d.GetMatrix())
|
||||
|
||||
@abstractmethod
|
||||
def _post_set_update(self):
|
||||
"""Update object after setting Prop3D attributes."""
|
||||
|
||||
@abstractmethod
|
||||
def _get_bounds(self) -> BoundsTuple:
|
||||
"""Return the object's 3D bounds."""
|
||||
|
||||
@property
|
||||
@wraps(Prop3D.bounds.fget) # type: ignore[attr-defined]
|
||||
def bounds(self) -> BoundsTuple: # numpydoc ignore=RT01
|
||||
"""Wrap :class:`pyvista.Prop3D.bounds`."""
|
||||
return BoundsTuple(*self._get_bounds())
|
||||
|
||||
@property
|
||||
@wraps(Prop3D.center.fget) # type: ignore[attr-defined]
|
||||
def center(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
||||
"""Wrap :class:`pyvista.Prop3D.center."""
|
||||
bnds = self.bounds
|
||||
return (
|
||||
(bnds.x_min + bnds.x_max) / 2,
|
||||
(bnds.y_min + bnds.y_max) / 2,
|
||||
(bnds.z_min + bnds.z_max) / 2,
|
||||
)
|
||||
|
||||
@property
|
||||
@wraps(Prop3D.length.fget) # type: ignore[attr-defined]
|
||||
def length(self) -> float: # numpydoc ignore=RT01
|
||||
"""Wrap :class:`pyvista.Prop3D.length."""
|
||||
bnds = self.bounds
|
||||
return np.linalg.norm(
|
||||
(bnds.x_max - bnds.x_min, bnds.y_max - bnds.y_min, bnds.z_max - bnds.z_min)
|
||||
).tolist()
|
||||
Reference in New Issue
Block a user