diff --git a/fastplotlib/graphics/_base.py b/fastplotlib/graphics/_base.py index 91ccb143e..f7a0ec102 100644 --- a/fastplotlib/graphics/_base.py +++ b/fastplotlib/graphics/_base.py @@ -5,6 +5,7 @@ from dataclasses import dataclass import numpy as np +import pylinalg as la from pygfx import WorldObject @@ -142,6 +143,14 @@ def position_y(self, val): def position_z(self, val): self.world_object.world.z = val + @property + def rotation(self): + return self.world_object.local.rotation + + @rotation.setter + def rotation(self, val): + self.world_object.local.rotation = val + @property def visible(self) -> bool: """Access or change the visibility.""" @@ -196,6 +205,28 @@ def __del__(self): self.deleted = True del WORLD_OBJECTS[self.loc] + def rotate(self, alpha: float, axis: Literal["x", "y", "z"] = "y"): + """Rotate the Graphic with respect to the world. + + Parameters + ---------- + alpha : + Rotation angle in radians. + axis : + Rotation axis label. + """ + if axis == "x": + rot = la.quat_from_euler((alpha, 0), order="XY") + elif axis == "y": + rot = la.quat_from_euler((0, alpha), order="XY") + elif axis == "z": + rot = la.quat_from_euler((0, alpha), order="XZ") + else: + raise ValueError( + f"`axis` must be either `x`, `y`, or `z`. `{axis}` provided instead!" + ) + self.rotation = la.quat_mul(rot, self.rotation) + class Interaction(ABC): """Mixin class that makes graphics interactive"""