"""Finger 3D mesh viewer with example-only contact arrow overlay.""" from __future__ import annotations from orisys.finger.viewer import UVMeshViewer from .contact_arrow import ContactArrowOverlay, ContactArrowStyle, DEFAULT_CONTACT_ARROW_STYLE class FingerMeshViewer(UVMeshViewer): """UV mesh viewer with a force-scaled contact normal arrow.""" def __init__( self, mesh, *, max_magnitude=None, threshold: float = 0.0, color_mode: str = "flow", value_min=None, value_max=None, window_width: int = 1024, window_height: int = 1024, contact_arrow_style: ContactArrowStyle | None = None, normal_force_scale: float | None = None, show_contact_arrow: bool = True, ): super().__init__( mesh, max_magnitude=max_magnitude, threshold=threshold, color_mode=color_mode, value_min=value_min, value_max=value_max, window_width=window_width, window_height=window_height, ) self._contact_arrow = ContactArrowOverlay( mesh, style=contact_arrow_style or DEFAULT_CONTACT_ARROW_STYLE, normal_force_scale=normal_force_scale, enabled=show_contact_arrow, ) def _extra_geometries_for_init(self): if self._contact_arrow.arrow_mesh is None: return [] return [self._contact_arrow.arrow_mesh] def _extra_geometries_for_update(self): if self._contact_arrow.arrow_mesh is None: return [] return [self._contact_arrow.arrow_mesh] def update( self, flow=None, scalar_map=None, *, centroid=None, centroid_found: bool = False, fnormal: float = 0.0, ): arrow = self._contact_arrow.compute(centroid, centroid_found, fnormal) if arrow is not None and self._contact_arrow.arrow_mesh is not None: arrow_vertices, _, arrow_colors = arrow self._contact_arrow.apply(arrow_vertices, arrow_colors) return super().update(flow=flow, scalar_map=scalar_map)