This commit is contained in:
cjw
2026-02-12 23:22:11 +08:00
parent 7b09eb3d89
commit 89660bba4e
5988 changed files with 2517516 additions and 0 deletions
@@ -0,0 +1,455 @@
"""Wrap :vtk:`vtkActor` module."""
from __future__ import annotations
from typing import TYPE_CHECKING
import numpy as np
import pyvista
from pyvista._deprecate_positional_args import _deprecate_positional_args
from . import _vtk
from ._property import Property
from .prop3d import Prop3D
if TYPE_CHECKING:
from typing_extensions import Self
from .mapper import _BaseMapper
class Actor(Prop3D, _vtk.vtkActor):
"""Wrap :vtk:`vtkActor`.
This class represents the geometry & properties in a rendered
scene. Normally, a :class:`pyvista.Actor` is constructed from
:func:`pyvista.Plotter.add_mesh`, but there may be times when it is more
convenient to construct an actor directly from a
:class:`pyvista.DataSetMapper`.
Parameters
----------
mapper : pyvista.DataSetMapper, optional
DataSetMapper.
prop : pyvista.Property, optional
Property of the actor.
name : str, optional
The name of this actor used when tracking on a plotter.
Examples
--------
Create an actor without using :class:`pyvista.Plotter`.
>>> import pyvista as pv
>>> mesh = pv.Sphere()
>>> mapper = pv.DataSetMapper(mesh)
>>> actor = pv.Actor(mapper=mapper)
>>> actor
Actor (...)
Center: (0.0, 0.0, 0.0)
Pickable: True
Position: (0.0, 0.0, 0.0)
Scale: (1.0, 1.0, 1.0)
Visible: True
X Bounds -4.993E-01, 4.993E-01
Y Bounds -4.965E-01, 4.965E-01
Z Bounds -5.000E-01, 5.000E-01
User matrix: Identity
Has mapper: True
...
Change the actor properties and plot the actor.
>>> import pyvista as pv
>>> mesh = pv.Sphere()
>>> mapper = pv.DataSetMapper(mesh)
>>> actor = pv.Actor(mapper=mapper)
>>> actor.prop.color = 'blue'
>>> actor.plot()
Create an actor using the :class:`pyvista.Plotter` and then change the
visibility of the actor.
>>> import pyvista as pv
>>> pl = pv.Plotter()
>>> mesh = pv.Sphere()
>>> actor = pl.add_mesh(mesh)
>>> actor.visibility = False
>>> actor.visibility
False
"""
def __init__(self, mapper=None, prop=None, name=None) -> None:
"""Initialize actor."""
super().__init__()
if mapper is not None:
self.mapper = mapper
if prop is None:
self.prop = Property()
else:
self.prop = prop
self._name = name
@property
def mapper(self) -> _BaseMapper: # numpydoc ignore=RT01
"""Return or set the mapper of the actor.
Examples
--------
Create an actor and assign a mapper to it.
>>> import pyvista as pv
>>> dataset = pv.Sphere()
>>> actor = pv.Actor()
>>> actor.mapper = pv.DataSetMapper(dataset)
>>> actor.mapper
DataSetMapper (...)
Scalar visibility: True
Scalar range: (0.0, 1.0)
Interpolate before mapping: True
Scalar map mode: default
Color mode: direct
<BLANKLINE>
Attached dataset:
PolyData (...)
N Cells: 1680
N Points: 842
N Strips: 0
X Bounds: -4.993e-01, 4.993e-01
Y Bounds: -4.965e-01, 4.965e-01
Z Bounds: -5.000e-01, 5.000e-01
N Arrays: 1
"""
return self.GetMapper() # type: ignore[return-value]
@mapper.setter
def mapper(self, obj) -> None:
self.SetMapper(obj)
@property
def prop(self): # numpydoc ignore=RT01
"""Return or set the property of this actor.
Examples
--------
Modify the properties of an actor after adding a dataset to the plotter.
>>> import pyvista as pv
>>> pl = pv.Plotter()
>>> actor = pl.add_mesh(pv.Sphere())
>>> prop = actor.prop
>>> prop.diffuse = 0.6
>>> pl.show()
"""
return self.GetProperty()
@prop.setter
def prop(self, obj: Property) -> None:
self.SetProperty(obj)
@property
def texture(self): # numpydoc ignore=RT01
"""Return or set the actor texture.
Notes
-----
The mapper dataset must have texture coordinates for the texture to be
used.
Examples
--------
Create an actor and add a texture to it. Note how the
:class:`pyvista.PolyData` has texture coordinates by default.
>>> import pyvista as pv
>>> from pyvista import examples
>>> plane = pv.Plane()
>>> plane.active_texture_coordinates is not None
True
>>> pl = pv.Plotter()
>>> actor = pl.add_mesh(plane)
>>> actor.texture = examples.download_masonry_texture()
>>> actor.texture
Texture (...)
Components: 3
Cube Map: False
Dimensions: 256, 256
"""
return self.GetTexture()
@texture.setter
def texture(self, obj) -> None:
self.SetTexture(obj)
@property
def memory_address(self): # numpydoc ignore=RT01
"""Return the memory address of this actor."""
return self.GetAddressAsString('')
@property
def pickable(self) -> bool: # numpydoc ignore=RT01
"""Return or set actor pickability.
Examples
--------
Create an actor using the :class:`pyvista.Plotter` and then make the
actor unpickable.
>>> import pyvista as pv
>>> pl = pv.Plotter()
>>> actor = pl.add_mesh(pv.Sphere())
>>> actor.pickable = False
>>> actor.pickable
False
"""
return bool(self.GetPickable())
@pickable.setter
def pickable(self, value) -> None:
self.SetPickable(value)
@property
def visibility(self) -> bool: # numpydoc ignore=RT01
"""Return or set actor visibility.
See Also
--------
use_bounds
pyvista.Plotter.compute_bounds
Examples
--------
Create an actor using the :class:`pyvista.Plotter` and then change the
visibility of the actor.
>>> import pyvista as pv
>>> from pyvista import examples
>>> mesh = examples.load_airplane()
>>> pl = pv.Plotter()
>>> actor = pl.add_mesh(mesh)
>>> pl.bounds
BoundsTuple(x_min = 139.06100463867188,
x_max = 1654.9300537109375,
y_min = 32.09429931640625,
y_max = 1319.949951171875,
z_min = -17.741199493408203,
z_max = 282.1300048828125)
>>> actor.visibility = False
>>> pl.bounds
BoundsTuple(x_min = -1.0,
x_max = 1.0,
y_min = -1.0,
y_max = 1.0,
z_min = -1.0,
z_max = 1.0)
"""
return bool(self.GetVisibility())
@visibility.setter
def visibility(self, value: bool) -> None:
self.SetVisibility(value)
@property
def use_bounds(self) -> bool: # numpydoc ignore=RT01
"""Return or set the use of actor's bounds.
.. versionadded:: 0.45
See Also
--------
visibility
pyvista.Plotter.compute_bounds
Examples
--------
Create an actor using the :class:`pyvista.Plotter` and then change the
use of bounds for the actor.
>>> import pyvista as pv
>>> from pyvista import examples
>>> mesh = examples.load_airplane()
>>> pl = pv.Plotter()
>>> actor = pl.add_mesh(mesh)
>>> pl.bounds
BoundsTuple(x_min = 139.06100463867188,
x_max = 1654.9300537109375,
y_min = 32.09429931640625,
y_max = 1319.949951171875,
z_min = -17.741199493408203,
z_max = 282.1300048828125)
>>> actor.use_bounds = False
>>> pl.bounds
BoundsTuple(x_min = -1.0,
x_max = 1.0,
y_min = -1.0,
y_max = 1.0,
z_min = -1.0,
z_max = 1.0)
Although the actor's bounds are no longer used, the actor remains visible.
>>> actor.visibility
True
"""
return bool(self.GetUseBounds())
@use_bounds.setter
def use_bounds(self, value: bool) -> None:
self.SetUseBounds(value)
def plot(self, **kwargs) -> None:
"""Plot just the actor.
This may be useful when interrogating or debugging individual actors.
Parameters
----------
**kwargs : dict, optional
Optional keyword arguments passed to :func:`pyvista.Plotter.show`.
Examples
--------
Create an actor without the :class:`pyvista.Plotter`, change its
properties, and plot it.
>>> import pyvista as pv
>>> mesh = pv.Sphere()
>>> mapper = pv.DataSetMapper(mesh)
>>> actor = pv.Actor(mapper=mapper)
>>> actor.prop.color = 'red'
>>> actor.prop.show_edges = True
>>> actor.plot()
"""
pl = pyvista.Plotter()
pl.add_actor(self)
pl.show(**kwargs)
@_deprecate_positional_args
def copy(self: Self, deep: bool = True) -> Self: # noqa: FBT001, FBT002
"""Create a copy of this actor.
Parameters
----------
deep : bool, default: True
Create a shallow or deep copy of the actor. A deep copy will have a
new property and mapper, while a shallow copy will use the mapper
and property of this actor.
Returns
-------
Actor
Deep or shallow copy of this actor.
Examples
--------
Create an actor of a cube by adding it to a :class:`~pyvista.Plotter`
and then copy the actor, change the properties, and add it back to the
:class:`~pyvista.Plotter`.
>>> import pyvista as pv
>>> mesh = pv.Cube()
>>> pl = pv.Plotter()
>>> actor = pl.add_mesh(mesh, color='b')
>>> new_actor = actor.copy()
>>> new_actor.prop.style = 'wireframe'
>>> new_actor.prop.line_width = 5
>>> new_actor.prop.color = 'r'
>>> new_actor.prop.lighting = False
>>> _ = pl.add_actor(new_actor)
>>> pl.show()
"""
new_actor = type(self)()
if deep:
if self.mapper is not None:
new_actor.mapper = self.mapper.copy()
new_actor.prop = self.prop.copy()
else:
new_actor.ShallowCopy(self)
return new_actor
def __repr__(self):
"""Representation of the actor."""
mat_info = 'Identity' if np.array_equal(self.user_matrix, np.eye(4)) else 'Set'
bnd = self.bounds
attr = [
f'{type(self).__name__} ({hex(id(self))})',
f' Center: {self.center}',
f' Pickable: {self.pickable}',
f' Position: {self.position}',
f' Scale: {self.scale}',
f' Visible: {self.visibility}',
f' X Bounds {bnd[0]:.3E}, {bnd[1]:.3E}',
f' Y Bounds {bnd[2]:.3E}, {bnd[3]:.3E}',
f' Z Bounds {bnd[4]:.3E}, {bnd[5]:.3E}',
f' User matrix: {mat_info}',
f' Has mapper: {self.mapper is not None}',
'',
repr(self.prop),
]
if self.mapper is not None:
attr.append('')
attr.append(repr(self.mapper))
return '\n'.join(attr)
@property
def backface_prop(self) -> pyvista.Property | None: # numpydoc ignore=RT01
"""Return or set the backface property.
By default this property matches the frontface property
:attr:`Actor.prop`. Once accessed or modified, this backface
property becomes independent of the frontface property. In
order to restore the fallback to frontface property, assign
``None`` to the property.
Returns
-------
pyvista.Property
The object describing backfaces.
See Also
--------
:ref:`backface_prop_example`
Examples
--------
Clip a sphere by a plane and color the inside of the clipped sphere
light blue using the ``backface_prop``.
>>> import numpy as np
>>> import pyvista as pv
>>> plane = pv.Plane(i_size=1.5, j_size=1.5)
>>> mesh = pv.Sphere().clip_surface(plane, invert=False)
>>> pl = pv.Plotter()
>>> actor = pl.add_mesh(mesh, smooth_shading=True)
>>> actor.backface_prop.color = 'lightblue'
>>> _ = pl.add_mesh(
... plane,
... opacity=0.25,
... show_edges=True,
... color='grey',
... lighting=False,
... )
>>> pl.show()
"""
if self.GetBackfaceProperty() is None:
self.SetBackfaceProperty(self.prop.copy())
return self.GetBackfaceProperty() # type: ignore[return-value]
@backface_prop.setter
def backface_prop(self, value: pyvista.Property) -> None:
self.SetBackfaceProperty(value)