Source code for magicclass.ext.vtk.components

from __future__ import annotations
from typing import Callable, Generic, Sequence, TypeVar, overload
from typing_extensions import ParamSpec
import weakref
import vedo
import numpy as np
from .const import Representation

_VtkType = TypeVar("_VtkType", bound=vedo.BaseActor)
_P = ParamSpec("_P")
_L = TypeVar("_L", bound="VtkComponent")
_V = TypeVar("_V")


[docs]class VtkProperty(property, Generic[_L, _V]): def __init__( self, vedo_fname: str | None = None, vtk_fname: str | None = None, converter: type | None = None, doc: str | None = None, **kwargs, ): if converter is None: converter = lambda x: x self._converter = converter if vedo_fname is not None: fget, fset = self._from_vedo(vedo_fname, **kwargs) else: fget, fset = self._from_vtk(f"Get{vtk_fname}", f"Set{vtk_fname}", **kwargs) super().__init__(fget, fset, doc=doc) def _from_vedo(self, vedo_fname: str, **kwargs): # getter function def fget(x: _L) -> _V: return self._converter(getattr(x._obj, vedo_fname)()) # setter function def fset(x: _L, value: _V) -> None: getattr(x._obj, vedo_fname)(self._converter(value), **kwargs) x._update() return fget, fset def _from_vtk(self, fget_name: str, fset_name: str, **kwargs): # getter function def fget(x: _L) -> _V: return self._converter(getattr(x._obj.GetProperty(), fget_name)()) # setter function def fset(x: _L, value: _V) -> None: getattr(x._obj.GetProperty(), fset_name)(self._converter(value), **kwargs) x._update() return fget, fset
[docs]class VtkComponent: _vtk_type: type[_VtkType] | Callable[_P, _VtkType] def __init__(self, *args, _parent: vedo.Plotter = None, **kwargs): if self._vtk_type is None: raise TypeError("Base VTK type is unknown.") self._obj = self._vtk_type(*args, **kwargs) self._parent_ref = weakref.ref(_parent) self._set_properties() def _set_properties(self): pass @overload def __init_subclass__(cls, base: type[_VtkType] = None) -> None: # noqa ... @overload def __init_subclass__(cls, base: Callable[_P, _VtkType] = None) -> None: # noqa ... def __init_subclass__(cls, base=None) -> None: cls._vtk_type = base visible: VtkProperty[VtkComponent, bool] = VtkProperty( vtk_fname="Visibility", converter=bool, doc="Visibility of the object." ) def _update(self): self._parent_ref().window.Render() def __repr__(self) -> str: return f"{self.__class__.__name__}<{hex(id(self))}>"
[docs]class Points(VtkComponent, base=vedo.Points): # fmt: off color: VtkProperty[Points, np.ndarray] = VtkProperty("color", doc="Point color.") # noqa point_size: VtkProperty[Points, float] = VtkProperty(vtk_fname="PointSize", converter=float, doc="Size of points.") # noqa spherical: VtkProperty[Points, float] = VtkProperty(vtk_fname="RenderPointsAsSpheres", converter=float, doc="Render points to look spherical") # noqa occlusion: VtkProperty[Points, float] = VtkProperty("occlusion", doc="Occlusion strength.") # noqa pos: VtkProperty[Points, Sequence[float]] = VtkProperty("pos", doc="position the points.") # noqa scale: VtkProperty[Points, float] = VtkProperty("scale", absolute=True, doc="scale of the layer.") # noqa
# fmt: on
[docs]class Mesh(Points, base=vedo.Mesh): def _set_properties(self): super()._set_properties() self._representation = Representation.surface # fmt: off linewidth: VtkProperty[Mesh, float] = VtkProperty("lineWidth", doc="Line width of edges.") # noqa backface_color: VtkProperty[Mesh, np.ndarray] = VtkProperty("backColor", doc="Color of the backside of polygons.") # noqa frontface_culling: VtkProperty[Points, bool] = VtkProperty(vtk_fname="FrontfaceCulling", converter=bool, doc="Culling of front face.") # noqa backface_culling: VtkProperty[Points, bool] = VtkProperty(vtk_fname="BackfaceCulling", converter=bool, doc="Culling of back face.") # noqa lines_as_tubes: VtkProperty[Points, bool] = VtkProperty(vtk_fname="RenderLinesAsTubes", converter=bool, doc="Render mesh lines as tubes.") # noqa # fmt: on @property def representation(self) -> Representation: """ Representation mode of mesh. One of "points", "wireframe", "surface". """ return self._representation.name @representation.setter def representation(self, value) -> None: rep: Representation = getattr(Representation, value) self._obj.property.SetRepresentation(rep.value) self._representation = rep self._update()
# fmt: off
[docs]class Path(Mesh, base=vedo.Line): ...
[docs]class Sphere(Mesh, base=vedo.Sphere): ...
[docs]class Spheres(Mesh, base=vedo.Spheres): ...
[docs]class Spline(Mesh, base=vedo.Spline): ...
[docs]class KSpline(Mesh, base=vedo.KSpline): ...
[docs]class CSpline(Mesh, base=vedo.CSpline): ...
[docs]class Tube(Mesh, base=vedo.Tube): ...
[docs]class Ribbon(Mesh, base=vedo.Ribbon): ...
[docs]class Arrow(Mesh, base=vedo.Arrow): ...
[docs]class Arrows(Mesh, base=vedo.Arrows): ...
[docs]class Circle(Mesh, base=vedo.Circle): ...
[docs]class Disc(Mesh, base=vedo.Disc): ...
[docs]class Earth(Mesh, base=vedo.Earth): ...
[docs]class Ellipsoid(Mesh, base=vedo.Ellipsoid): ...
[docs]class Box(Mesh, base=vedo.Box): ...
[docs]class Cube(Mesh, base=vedo.Cube): ...
[docs]class Spring(Mesh, base=vedo.Spring): ...
[docs]class Cylinder(Mesh, base=vedo.Cylinder): ...
[docs]class Cone(Mesh, base=vedo.Cone): ...
[docs]class Text(Mesh, base=vedo.Text3D): ...
# fmt: on
[docs]def get_object_type(name: str) -> type[VtkComponent]: t = globals().get(name, None) if not isinstance(t, (type, Generic)): raise ValueError(f"Object type {t} not found.") elif not issubclass(t, VtkComponent): raise ValueError(f"Object type {t} not found.") return t