875 lines
24 KiB
Python
875 lines
24 KiB
Python
"""Contains the pyvista.Text class."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pathlib
|
|
from pathlib import Path
|
|
from typing import TYPE_CHECKING
|
|
from typing import Literal
|
|
|
|
import pyvista
|
|
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.misc import _check_range
|
|
from pyvista.core.utilities.misc import _NameMixin
|
|
from pyvista.core.utilities.misc import _NoNewAttrMixin
|
|
|
|
from . import _vtk
|
|
from .colors import Color
|
|
from .prop3d import _Prop3DMixin
|
|
from .themes import Theme
|
|
from .tools import FONTS
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Sequence
|
|
|
|
from pyvista.core._typing_core import VectorLike
|
|
|
|
from ._typing import ColorLike
|
|
|
|
HorizontalOptions = Literal['left', 'center', 'right']
|
|
VerticalOptions = Literal['bottom', 'center', 'top']
|
|
|
|
|
|
class CornerAnnotation(
|
|
_NoNewAttrMixin, _vtk.DisableVtkSnakeCase, _NameMixin, _vtk.vtkCornerAnnotation
|
|
):
|
|
"""Text annotation in four corners.
|
|
|
|
This is an annotation object that manages four text actors / mappers to provide
|
|
annotation in the four corners of a viewport.
|
|
|
|
Parameters
|
|
----------
|
|
position : str | bool
|
|
Position of the text.
|
|
|
|
text : str
|
|
Text input.
|
|
|
|
prop : pyvista.TextProperty, optional
|
|
Text property.
|
|
|
|
linear_font_scale_factor : float, optional
|
|
Linear font scale factor.
|
|
|
|
name : str, optional
|
|
The name of this actor used when tracking on a plotter.
|
|
|
|
.. versionadded:: 0.45
|
|
|
|
Examples
|
|
--------
|
|
Create text annotation in four corners.
|
|
|
|
>>> from pyvista import CornerAnnotation
|
|
>>> text = CornerAnnotation(0, 'text')
|
|
>>> prop = text.prop
|
|
|
|
"""
|
|
|
|
@_deprecate_positional_args(allowed=['position', 'text'])
|
|
def __init__( # noqa: PLR0917
|
|
self, position, text, prop=None, linear_font_scale_factor=None, name=None
|
|
):
|
|
"""Initialize a new text annotation descriptor."""
|
|
super().__init__()
|
|
self.set_text(position, text)
|
|
if prop is None:
|
|
self.prop = TextProperty()
|
|
if linear_font_scale_factor is not None:
|
|
self.linear_font_scale_factor = linear_font_scale_factor
|
|
self._name = name
|
|
|
|
def get_text(self, position):
|
|
"""Get the text to be displayed for each corner.
|
|
|
|
Parameters
|
|
----------
|
|
position : str | bool
|
|
Position of the text.
|
|
|
|
Returns
|
|
-------
|
|
str
|
|
Text to be displayed for each corner.
|
|
|
|
"""
|
|
return self.GetText(position)
|
|
|
|
def set_text(self, position, text):
|
|
"""Set the text to be displayed for each corner.
|
|
|
|
Parameters
|
|
----------
|
|
position : str | bool
|
|
Position of the text.
|
|
|
|
text : str
|
|
Text to be displayed for each corner.
|
|
|
|
"""
|
|
corner_mappings = {
|
|
'lower_left': self.LowerLeft,
|
|
'lower_right': self.LowerRight,
|
|
'upper_left': self.UpperLeft,
|
|
'upper_right': self.UpperRight,
|
|
'lower_edge': self.LowerEdge,
|
|
'upper_edge': self.UpperEdge,
|
|
'left_edge': self.LeftEdge,
|
|
'right_edge': self.RightEdge,
|
|
}
|
|
corner_mappings['ll'] = corner_mappings['lower_left']
|
|
corner_mappings['lr'] = corner_mappings['lower_right']
|
|
corner_mappings['ul'] = corner_mappings['upper_left']
|
|
corner_mappings['ur'] = corner_mappings['upper_right']
|
|
corner_mappings['top'] = corner_mappings['upper_edge']
|
|
corner_mappings['bottom'] = corner_mappings['lower_edge']
|
|
corner_mappings['right'] = corner_mappings['right_edge']
|
|
corner_mappings['r'] = corner_mappings['right_edge']
|
|
corner_mappings['left'] = corner_mappings['left_edge']
|
|
corner_mappings['l'] = corner_mappings['left_edge']
|
|
if isinstance(position, str):
|
|
position = corner_mappings[position]
|
|
elif position is True:
|
|
position = corner_mappings['upper_left']
|
|
self.SetText(position, text)
|
|
|
|
@property
|
|
def prop(self) -> TextProperty:
|
|
"""Property of this actor.
|
|
|
|
Returns
|
|
-------
|
|
pyvista.TextProperty
|
|
Property of this actor.
|
|
|
|
"""
|
|
return self.GetTextProperty()
|
|
|
|
@prop.setter
|
|
def prop(self, prop: TextProperty):
|
|
self.SetTextProperty(prop)
|
|
|
|
@property
|
|
def linear_font_scale_factor(self) -> float:
|
|
"""Font scaling factors.
|
|
|
|
Returns
|
|
-------
|
|
float
|
|
Font scaling factors.
|
|
|
|
"""
|
|
return self.GetLinearFontScaleFactor()
|
|
|
|
@linear_font_scale_factor.setter
|
|
def linear_font_scale_factor(self, factor: float):
|
|
self.SetLinearFontScaleFactor(factor)
|
|
|
|
|
|
class Text(_NoNewAttrMixin, _vtk.DisableVtkSnakeCase, _NameMixin, _vtk.vtkTextActor):
|
|
r"""Define text by default theme.
|
|
|
|
Parameters
|
|
----------
|
|
text : str, optional
|
|
Text string to be displayed.
|
|
"\n" is recognized as a carriage return/linefeed (line separator).
|
|
The characters must be in the UTF-8 encoding.
|
|
|
|
position : Sequence[float], optional
|
|
The position coordinate.
|
|
|
|
prop : pyvista.TextProperty, optional
|
|
The property of this actor.
|
|
|
|
name : str, optional
|
|
The name of this actor used when tracking on a plotter.
|
|
|
|
.. versionadded:: 0.45
|
|
|
|
Examples
|
|
--------
|
|
Create a text with text's property.
|
|
|
|
>>> from pyvista import Text
|
|
>>> text = Text()
|
|
>>> prop = text.prop
|
|
|
|
"""
|
|
|
|
@_deprecate_positional_args(allowed=['text'])
|
|
def __init__( # noqa: PLR0917
|
|
self, text=None, position=None, prop=None, name=None
|
|
):
|
|
"""Initialize a new text descriptor."""
|
|
super().__init__()
|
|
if text is not None:
|
|
self.input = text
|
|
if position is not None:
|
|
self.position = position
|
|
if prop is None:
|
|
self.prop = TextProperty()
|
|
self._name = name
|
|
|
|
@property
|
|
def input(self):
|
|
r"""Text string to be displayed.
|
|
|
|
Returns
|
|
-------
|
|
str
|
|
Text string to be displayed.
|
|
"\n" is recognized as a carriage return/linefeed (line separator).
|
|
The characters must be in the UTF-8 encoding.
|
|
|
|
"""
|
|
return self.GetInput()
|
|
|
|
@input.setter
|
|
def input(self, text: str):
|
|
self.SetInput(text)
|
|
|
|
@property
|
|
def prop(self):
|
|
"""Property of this actor.
|
|
|
|
Returns
|
|
-------
|
|
pyvista.TextProperty
|
|
Property of this actor.
|
|
|
|
"""
|
|
return self.GetTextProperty()
|
|
|
|
@prop.setter
|
|
def prop(self, prop: TextProperty):
|
|
self.SetTextProperty(prop)
|
|
|
|
@property
|
|
def position(self):
|
|
"""Position coordinate.
|
|
|
|
Returns
|
|
-------
|
|
Sequence[float]
|
|
Position coordinate.
|
|
|
|
"""
|
|
return self.GetPosition()
|
|
|
|
@position.setter
|
|
def position(self, position: Sequence[float]):
|
|
self.SetPosition(position[0], position[1])
|
|
|
|
|
|
class Label(_Prop3DMixin, Text):
|
|
"""2D label actor with a 3D position coordinate.
|
|
|
|
Unlike :class:`~pyvista.Text`, which uses 2D viewport coordinates to position text
|
|
in a plot, this class instead uses a 3D position coordinate. This class may be
|
|
positioned, oriented, and transformed in a manner similar to a 3D
|
|
:class:`~pyvista.Actor`.
|
|
|
|
In addition, this class supports an additional :attr:`relative_position` attribute.
|
|
In general, it is recommended to simply use :attr:`~pyvista.Prop3D.position` when positioning a
|
|
:class:`Label` by itself. However, if the position of the label depends on the
|
|
positioning of another actor, both :attr:`~pyvista.Prop3D.position` and
|
|
:attr:`relative_position` may be used together.
|
|
In these cases, the :attr:`~pyvista.Prop3D.position` of the label and actor
|
|
should be kept in-sync. See the examples below.
|
|
|
|
Parameters
|
|
----------
|
|
text : str, optional
|
|
Text string to be displayed.
|
|
|
|
position : VectorLike[float]
|
|
Position of the text in XYZ coordinates.
|
|
|
|
relative_position : VectorLike[float]
|
|
Position of the text in XYZ coordinates relative to its :attr:`~pyvista.Prop3D.position`.
|
|
|
|
size : int
|
|
Size of the text label.
|
|
|
|
prop : pyvista.TextProperty, optional
|
|
The property of this actor.
|
|
|
|
name : str, optional
|
|
The name of this actor used when tracking on a plotter.
|
|
|
|
.. versionadded:: 0.45
|
|
|
|
See Also
|
|
--------
|
|
pyvista.Plotter.add_point_labels
|
|
|
|
Examples
|
|
--------
|
|
Create a label for a point of interest. Here we add a label to the tip of a cone.
|
|
|
|
>>> import pyvista as pv
|
|
>>> cone_dataset = pv.Cone()
|
|
>>> tip = (0.5, 0, 0)
|
|
>>> label = pv.Label('tip', position=tip)
|
|
|
|
Plot the mesh and label.
|
|
|
|
>>> pl = pv.Plotter()
|
|
>>> cone_actor = pl.add_mesh(cone_dataset)
|
|
>>> _ = pl.add_actor(label)
|
|
>>> pl.show()
|
|
|
|
The previous example set the label's position as the cone's tip explicitly.
|
|
However, this means that the two actors now have different positions.
|
|
|
|
>>> cone_actor.position
|
|
(0.0, 0.0, 0.0)
|
|
>>> label.position
|
|
(0.5, 0.0, 0.0)
|
|
|
|
And if we change the 3D orientation of the cone and label, the label is no longer
|
|
positioned at the tip.
|
|
|
|
>>> cone_actor.orientation = 0, 0, 90
|
|
>>> label.orientation = 0, 0, 90
|
|
>>>
|
|
>>> pl = pv.Plotter()
|
|
>>> _ = pl.add_actor(cone_actor)
|
|
>>> _ = pl.add_actor(label)
|
|
>>> pl.show()
|
|
|
|
This is because rotations by :class:`pyvista.Prop3D` are applied **before** the
|
|
actor is moved to its final position, and therefore the label's position is not
|
|
considered in the rotation. Hence, the final position of the label remains at
|
|
``(0.5, 0.0, 0.0)`` as it did earlier, despite changing its orientation.
|
|
|
|
If we want the position of the label to have the same positioning *relative* to the
|
|
cone, we can instead set its :attr:`relative_position`.
|
|
|
|
First, reset the label's position to match the cone's position.
|
|
|
|
>>> label.position = cone_actor.position
|
|
>>> label.position
|
|
(0.0, 0.0, 0.0)
|
|
|
|
Now set its :attr:`relative_position` to the tip of the cone.
|
|
|
|
>>> label.relative_position = tip
|
|
>>> label.relative_position
|
|
(0.5, 0.0, 0.0)
|
|
|
|
Plot the results. The label is now correctly positioned at the tip of the cone.
|
|
This is because the :attr:`relative_position` is considered as part of the
|
|
rotation.
|
|
|
|
>>> pl = pv.Plotter()
|
|
>>> _ = pl.add_actor(cone_actor)
|
|
>>> _ = pl.add_actor(label)
|
|
>>> pl.show()
|
|
|
|
As long as the label and cone's :class:`pyvista.Prop3D` attributes are modified
|
|
together and synchronized, the label will remain at the tip of the cone.
|
|
|
|
Modify the position of the label and tip.
|
|
|
|
>>> cone_actor.position = (1.0, 2.0, 3.0)
|
|
>>> label.position = (1.0, 2.0, 3.0)
|
|
>>> pl = pv.Plotter()
|
|
>>> _ = pl.add_actor(cone_actor)
|
|
>>> _ = pl.add_actor(label)
|
|
>>> _ = pl.add_axes_at_origin()
|
|
>>> pl.show()
|
|
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
text: str | None = None,
|
|
position: VectorLike[float] = (0.0, 0.0, 0.0),
|
|
relative_position: VectorLike[float] = (0.0, 0.0, 0.0),
|
|
*,
|
|
size: int = 50,
|
|
prop: pyvista.Property | None = None,
|
|
name: str = 'Label',
|
|
):
|
|
Text.__init__(self, text=text, prop=prop)
|
|
self.GetPositionCoordinate().SetCoordinateSystemToWorld()
|
|
self.SetTextScaleModeToNone() # Use font size to control size of text
|
|
self._name = name
|
|
|
|
_Prop3DMixin.__init__(self)
|
|
self.relative_position = relative_position
|
|
self.position = position
|
|
self.size = size
|
|
|
|
@property
|
|
def _label_position(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
|
"""Position of the label in xyz space.
|
|
|
|
This is the "true" position of the label. Internally this is loosely
|
|
equal to :attr:`~pyvista.Prop3D.position` + :attr:`relative_position`.
|
|
"""
|
|
return self.GetPositionCoordinate().GetValue()
|
|
|
|
@_label_position.setter
|
|
def _label_position(self, position: VectorLike[float]):
|
|
valid_position = _validation.validate_array3(position)
|
|
self.GetPositionCoordinate().SetValue(valid_position)
|
|
|
|
@property
|
|
def size(self) -> int: # numpydoc ignore=RT01
|
|
"""Size of the text label.
|
|
|
|
Notes
|
|
-----
|
|
The text property's font size used to control the size of the label.
|
|
|
|
"""
|
|
return self.prop.font_size
|
|
|
|
@size.setter
|
|
def size(self, size: int):
|
|
self.prop.font_size = size
|
|
|
|
@property
|
|
def relative_position(self) -> tuple[float, float, float]: # numpydoc ignore=RT01
|
|
"""Position of the label relative to its :attr:`~pyvista.Prop3D.position`."""
|
|
return tuple(self._relative_position.tolist())
|
|
|
|
@relative_position.setter
|
|
def relative_position(self, position: VectorLike[float]):
|
|
self._relative_position = _validation.validate_array3(position, dtype_out=float)
|
|
self._post_set_update()
|
|
|
|
def _post_set_update(self):
|
|
# Update the label's underlying text position
|
|
matrix4x4 = self._transformation_matrix
|
|
vector4 = (*self.relative_position, 1)
|
|
new_position = (matrix4x4 @ vector4)[:3]
|
|
self._label_position = new_position
|
|
|
|
def _get_bounds(self) -> BoundsTuple:
|
|
# Define its 3D position as its bounds
|
|
x, y, z = self._label_position
|
|
return BoundsTuple(x, x, y, y, z, z)
|
|
|
|
|
|
class TextProperty(_NoNewAttrMixin, _vtk.DisableVtkSnakeCase, _vtk.vtkTextProperty):
|
|
"""Define text's property.
|
|
|
|
Parameters
|
|
----------
|
|
theme : pyvista.plotting.themes.Theme, optional
|
|
Plot-specific theme.
|
|
|
|
color : pyvista.ColorLike, optional
|
|
Either a string, RGB list, or hex color string. For example:
|
|
``color='white'``, ``color='w'``, ``color=[1.0, 1.0, 1.0]``, or
|
|
``color='#FFFFFF'``. Color will be overridden if scalars are
|
|
specified.
|
|
|
|
font_family : str | None, optional
|
|
Font family or None.
|
|
|
|
orientation : float, optional
|
|
Text's orientation (in degrees).
|
|
|
|
font_size : int, optional
|
|
Font size.
|
|
|
|
font_file : str, optional
|
|
Font file path.
|
|
|
|
shadow : bool, optional
|
|
If enable the shadow.
|
|
|
|
justification_horizontal : str, optional
|
|
Text's horizontal justification.
|
|
Should be either "left", "center" or "right".
|
|
|
|
justification_vertical : str, optional
|
|
Text's vertical justification.
|
|
Should be either "bottom", "center" or "top".
|
|
|
|
italic : bool, default: False
|
|
Italicises title and bar labels.
|
|
|
|
bold : bool, default: True
|
|
Bolds title and bar labels.
|
|
|
|
background_color : pyvista.Color, optional
|
|
Background color of text.
|
|
|
|
background_opacity : pyvista.Color, optional
|
|
Background opacity of text.
|
|
|
|
Examples
|
|
--------
|
|
Create a text's property.
|
|
|
|
>>> from pyvista import TextProperty
|
|
>>> prop = TextProperty()
|
|
>>> prop.opacity = 0.5
|
|
>>> prop.background_color = 'b'
|
|
>>> prop.background_opacity = 0.5
|
|
>>> prop.show_frame = True
|
|
>>> prop.frame_color = 'b'
|
|
>>> prop.frame_width = 10
|
|
>>> prop.frame_color
|
|
Color(name='blue', hex='#0000ffff', opacity=255)
|
|
|
|
"""
|
|
|
|
_theme = Theme()
|
|
_color_set = None
|
|
_background_color_set = None
|
|
_font_family = None
|
|
|
|
@_deprecate_positional_args(allowed=['theme'])
|
|
def __init__( # noqa: PLR0917
|
|
self,
|
|
theme=None,
|
|
color=None,
|
|
font_family=None,
|
|
orientation=None,
|
|
font_size=None,
|
|
font_file=None,
|
|
shadow: bool = False, # noqa: FBT001, FBT002
|
|
justification_horizontal=None,
|
|
justification_vertical=None,
|
|
italic: bool = False, # noqa: FBT001, FBT002
|
|
bold: bool = False, # noqa: FBT001, FBT002
|
|
background_color=None,
|
|
background_opacity=None,
|
|
):
|
|
"""Initialize text's property."""
|
|
super().__init__()
|
|
if theme is None:
|
|
# copy global theme to ensure local property theme is fixed
|
|
# after creation.
|
|
self._theme.load_theme(pyvista.global_theme)
|
|
else:
|
|
self._theme.load_theme(theme)
|
|
self.color = color
|
|
self.font_family = font_family
|
|
if orientation is not None:
|
|
self.orientation = orientation
|
|
if font_size is not None:
|
|
self.font_size = font_size
|
|
if font_file is not None:
|
|
self.set_font_file(font_file)
|
|
if shadow:
|
|
self.enable_shadow()
|
|
if justification_horizontal is not None:
|
|
self.justification_horizontal = justification_horizontal
|
|
if justification_vertical is not None:
|
|
self.justification_vertical = justification_vertical
|
|
self.italic = italic
|
|
self.bold = bold
|
|
if background_color is not None:
|
|
self.background_color = background_color
|
|
if background_opacity is not None:
|
|
self.background_opacity = background_opacity
|
|
|
|
@property
|
|
def color(self) -> Color:
|
|
"""Color of text's property.
|
|
|
|
Returns
|
|
-------
|
|
pyvista.Color
|
|
Color of text's property.
|
|
|
|
"""
|
|
return Color(self.GetColor())
|
|
|
|
@color.setter
|
|
def color(self, color: ColorLike):
|
|
self._color_set = color is not None
|
|
rgb_color = Color(color, default_color=self._theme.font.color)
|
|
self.SetColor(rgb_color.float_rgb)
|
|
|
|
@property
|
|
def opacity(self) -> float:
|
|
"""Opacity of text's property.
|
|
|
|
Returns
|
|
-------
|
|
float
|
|
Opacity of the text. A single float value that will be applied globally
|
|
opacity of the text and uniformly applied everywhere. Between 0 and 1.
|
|
|
|
"""
|
|
return self.GetOpacity()
|
|
|
|
@opacity.setter
|
|
def opacity(self, opacity: float):
|
|
_check_range(opacity, (0, 1), 'opacity')
|
|
self.SetOpacity(opacity)
|
|
|
|
@property
|
|
def background_color(self) -> Color:
|
|
"""Background color of text's property.
|
|
|
|
Returns
|
|
-------
|
|
pyvista.Color
|
|
Background color of text's property.
|
|
|
|
"""
|
|
return Color(self.GetBackgroundColor())
|
|
|
|
@background_color.setter
|
|
def background_color(self, color: ColorLike):
|
|
self._background_color_set = color is not None
|
|
rgb_color = Color(color)
|
|
self.SetBackgroundColor(rgb_color.float_rgb)
|
|
|
|
@property
|
|
def background_opacity(self) -> float:
|
|
"""Background opacity of text's property.
|
|
|
|
Returns
|
|
-------
|
|
float
|
|
Background opacity of the text. A single float value that will be applied globally.
|
|
Background opacity of the text and uniformly applied everywhere. Between 0 and 1.
|
|
|
|
"""
|
|
return self.GetBackgroundOpacity()
|
|
|
|
@background_opacity.setter
|
|
def background_opacity(self, opacity: float):
|
|
_check_range(opacity, (0, 1), 'background_opacity')
|
|
self.SetBackgroundOpacity(opacity)
|
|
|
|
@property
|
|
def show_frame(self) -> bool:
|
|
"""Visibility of frame.
|
|
|
|
Returns
|
|
-------
|
|
bool:
|
|
If shows the frame.
|
|
|
|
"""
|
|
return bool(self.GetFrame())
|
|
|
|
@show_frame.setter
|
|
def show_frame(self, frame: bool):
|
|
self.SetFrame(frame)
|
|
|
|
@property
|
|
def frame_color(self) -> Color:
|
|
"""Frame color of text property.
|
|
|
|
Returns
|
|
-------
|
|
pyvista.Color
|
|
Frame color of text property.
|
|
|
|
"""
|
|
return Color(self.GetFrameColor())
|
|
|
|
@frame_color.setter
|
|
def frame_color(self, color):
|
|
self.SetFrameColor(Color(color).float_rgb)
|
|
|
|
@property
|
|
def frame_width(self) -> int:
|
|
"""Width of the frame.
|
|
|
|
Returns
|
|
-------
|
|
int
|
|
Width of the frame. The width is expressed in pixels.
|
|
The default is 1 pixel.
|
|
|
|
"""
|
|
return self.GetFrameWidth()
|
|
|
|
@frame_width.setter
|
|
def frame_width(self, width: int):
|
|
self.SetFrameWidth(width)
|
|
|
|
@property
|
|
def font_family(self) -> str | None:
|
|
"""Font family.
|
|
|
|
Returns
|
|
-------
|
|
str | None
|
|
Font family or None.
|
|
|
|
"""
|
|
return self._font_family
|
|
|
|
@font_family.setter
|
|
def font_family(self, font_family: str | None):
|
|
if font_family is None:
|
|
font_family = self._theme.font.family
|
|
self._font_family = font_family
|
|
self.SetFontFamily(FONTS[self._font_family].value)
|
|
|
|
@property
|
|
def font_size(self) -> int:
|
|
"""Font size.
|
|
|
|
Returns
|
|
-------
|
|
int
|
|
Font size.
|
|
|
|
"""
|
|
return self.GetFontSize()
|
|
|
|
@font_size.setter
|
|
def font_size(self, font_size: int):
|
|
self.SetFontSize(font_size)
|
|
|
|
def enable_shadow(self) -> None:
|
|
"""Enable the shadow."""
|
|
self.SetShadow(True)
|
|
|
|
@property
|
|
def orientation(self) -> float:
|
|
"""Text's orientation (in degrees).
|
|
|
|
Returns
|
|
-------
|
|
float
|
|
Text's orientation (in degrees).
|
|
|
|
"""
|
|
return self.GetOrientation()
|
|
|
|
@orientation.setter
|
|
def orientation(self, orientation: float):
|
|
self.SetOrientation(orientation)
|
|
|
|
def set_font_file(self, font_file: str):
|
|
"""Set the font file.
|
|
|
|
Parameters
|
|
----------
|
|
font_file : str
|
|
Font file path.
|
|
|
|
"""
|
|
path = pathlib.Path(font_file)
|
|
path = path.resolve()
|
|
if not Path(path).is_file():
|
|
msg = f'Unable to locate {path}'
|
|
raise FileNotFoundError(msg)
|
|
self.SetFontFamily(_vtk.VTK_FONT_FILE)
|
|
self.SetFontFile(str(path))
|
|
|
|
@property
|
|
def justification_horizontal(self) -> str:
|
|
"""Text's justification horizontal.
|
|
|
|
Returns
|
|
-------
|
|
str
|
|
Text's horizontal justification.
|
|
Should be either "left", "center" or "right".
|
|
|
|
"""
|
|
justification = self.GetJustificationAsString().lower()
|
|
if justification == 'centered':
|
|
justification = 'center'
|
|
return justification
|
|
|
|
@justification_horizontal.setter
|
|
def justification_horizontal(self, justification: str):
|
|
if justification.lower() == 'left':
|
|
self.SetJustificationToLeft()
|
|
elif justification.lower() == 'center':
|
|
self.SetJustificationToCentered()
|
|
elif justification.lower() == 'right':
|
|
self.SetJustificationToRight()
|
|
else:
|
|
msg = (
|
|
f'Invalid {justification} for justification_horizontal. '
|
|
'Should be either "left", "center" or "right".'
|
|
)
|
|
raise ValueError(msg)
|
|
|
|
@property
|
|
def justification_vertical(self) -> str:
|
|
"""Text's vertical justification.
|
|
|
|
Returns
|
|
-------
|
|
str
|
|
Text's vertical justification.
|
|
Should be either "bottom", "center" or "top".
|
|
|
|
"""
|
|
justification = self.GetVerticalJustificationAsString().lower()
|
|
if justification == 'centered':
|
|
justification = 'center'
|
|
return justification
|
|
|
|
@justification_vertical.setter
|
|
def justification_vertical(self, justification: str):
|
|
if justification.lower() == 'bottom':
|
|
self.SetVerticalJustificationToBottom()
|
|
elif justification.lower() == 'center':
|
|
self.SetVerticalJustificationToCentered()
|
|
elif justification.lower() == 'top':
|
|
self.SetVerticalJustificationToTop()
|
|
else:
|
|
msg = (
|
|
f'Invalid {justification} for justification_vertical. '
|
|
'Should be either "bottom", "center" or "top".'
|
|
)
|
|
raise ValueError(msg)
|
|
|
|
@property
|
|
def italic(self) -> bool:
|
|
"""Italic of text's property.
|
|
|
|
Returns
|
|
-------
|
|
bool
|
|
If text is italic.
|
|
|
|
"""
|
|
return bool(self.GetItalic())
|
|
|
|
@italic.setter
|
|
def italic(self, italic: bool):
|
|
self.SetItalic(italic)
|
|
|
|
@property
|
|
def bold(self) -> bool:
|
|
"""Bold of text's property.
|
|
|
|
Returns
|
|
-------
|
|
bool
|
|
If text is bold.
|
|
|
|
"""
|
|
return bool(self.GetBold())
|
|
|
|
@bold.setter
|
|
def bold(self, bold: bool):
|
|
self.SetBold(bold)
|
|
|
|
def shallow_copy(self, to_copy: TextProperty) -> None:
|
|
"""Create a shallow copy of the text's property.
|
|
|
|
Parameters
|
|
----------
|
|
to_copy : pyvista.TextProperty
|
|
Text's property to copy from.
|
|
|
|
"""
|
|
self.ShallowCopy(to_copy)
|