Custom Converters#
Octarine
knows off the bat how to convert various data types to pygfx
visuals. When you throw data at e.g. Viewer.add
, Octarine
searches a set of known converter functions and tries to find one that fits the bill. If it can't find a matching converter it will complain.
In this tutorial you will learn how to generate and register new converter functions. See the Plugins tutorial on how to package these into a separate package.
First we will define a dummy class for our "custom data":
class Point3d:
"""Class representing a single 3d point."""
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
Next, we need to write a function that converts a Point3d
into a pygfx
object:
import pygfx as gfx
def convert_point3d(point, radius=1, color='red'):
"""Convert a Point3d to a pygfx Sphere."""
assert isinstance(point, Point3d)
# The geometry
geometry = gfx.geometries.sphere_geometry(radius=radius)
# The material
material = gfx.MeshPhongMaterial(color=color)
# Combine
mesh = gfx.Mesh(geometry, material)
# Set coordinates
mesh.local.position = (point.x, point.y, point.z)
# Return the mesh
return [mesh]
Now that we have a function that converts from Point3d
to a pygfx
visual, we need to tell Octarine
about it:
import octarine as oc
oc.register_converter(Point3d, convert_point3d)
With that we add a Point3d
to any viewer:
p = Point3d(1, 1, 1)
v = oc.Viewer()
v.add(p)
If you like can even add a specialized .add_...()
method:
@oc.viewer.update_viewer
def add_point3d(self, point, name=None, color=None, radius=1, center=True):
"""Add Point3d to canvas.
Parameters
----------
point : Point3D
Point to plot.
name : str, optional
Name for the visual.
color : str | tuple, optional
Color to use for the visual.
center : bool, optional
If True, re-center camera to all objects on canvas.
"""
# This grabs the next available color
if color is None:
color = self._next_color()
# Make sure we have a sensible name for our visual
if name is None:
name = self._next_label('Point')
elif not isinstance(name, str):
name = str(name)
visual = convert_point3d(point, color=color, radius=radius)
visual._object_id = name if name else uuid.uuid4()
self.scene.add(visual)
if center:
self.center_camera()
# Monkey patch the Viewer
oc.Viewer.add_point3d = add_point3d
Now this should work:
>>> p = Point3d(1, 1, 1)
>>> v = oc.Viewer()
>>> v.add_point3d(p)
OK, now you know how to write a custom converter. You could run the above code every time you start a new Python session but that gets old pretty quickly.
The more permanent solution is to write a Plugin that can be installed and is imported alongside Octarine
.