"""Pure-NumPy overlay geometry for Finger 3D arrows.""" from __future__ import annotations import numpy as np import pytest from orisys_app_shared.scene3d.overlays import ( arrow_instances_to_mesh, build_flow_overlay, build_normal_overlay, force_visual_strength, ) from orisys_app_shared.scene3d.synthetic import poc_scene from orisys_app_shared.scene3d.visual_policy import FlowSamples, VisualPolicy, select_flow_samples def test_force_visual_strength_is_capped() -> None: assert force_visual_strength(0.0) == 0.0 strong = force_visual_strength(1e9) mild = force_visual_strength(100.0) assert strong >= mild > 0.0 assert strong <= 1.0 + 1e-9 def test_flow_and_normal_overlays_on_poc_mapping() -> None: assets = poc_scene() mapping = assets.surface_mapping assert mapping is not None h, w = mapping.shape_hw flow = np.zeros((h, w, 2), dtype=np.float64) flow[1, 1] = (0.8, 0.0) mask = np.asarray(mapping.valid, dtype=bool) policy = VisualPolicy( flow_on_px=0.4, flow_grid_spacing=1, flow_edge_margin=0, max_arrows=50, ) samples = select_flow_samples(flow, mask, policy) arrows, diags = build_flow_overlay(samples, mapping, style=policy) assert not diags assert arrows is not None and arrows.origins.shape[0] >= 1 contact, cdiags = build_normal_overlay( contact_uv_xy=(1.0, 1.0), contact_found=True, contact_valid=True, fn=500.0, mapping=mapping, ) assert not cdiags assert contact is not None and contact.origins.shape[0] == 1 # Yellow-ish contact colour. assert float(contact.colors[0, 0]) > 0.7 assert float(contact.colors[0, 1]) > 0.7 positions, triangles, colors = arrow_instances_to_mesh(arrows) assert positions.ndim == 2 and positions.shape[1] == 3 assert triangles.ndim == 2 and triangles.shape[1] == 3 assert colors.shape[0] == positions.shape[0] def test_an_inactive_sample_is_a_grey_point_and_an_active_one_is_an_arrow() -> None: assets = poc_scene() mapping = assets.surface_mapping assert mapping is not None samples = FlowSamples( rows=np.asarray([1, 1], dtype=np.int32), cols=np.asarray([1, 2], dtype=np.int32), dx=np.asarray([0.8, 0.0]), dy=np.asarray([0.0, 0.0]), magnitude=np.asarray([1.6, 0.0]), active=np.asarray([True, False]), ) arrows, diags = build_flow_overlay(samples, mapping) assert not diags assert int(np.count_nonzero(arrows.lengths > 0.0)) == 1 assert int(np.count_nonzero(arrows.lengths < 0.0)) == 1 idle = arrows.colors[arrows.lengths < 0.0][0] # Brand idle tint #8A93A6, not a ramp colour. assert idle[0] == pytest.approx(0x8A / 255.0, abs=0.02) assert idle[2] == pytest.approx(0xA6 / 255.0, abs=0.02) positions, _triangles, colors = arrow_instances_to_mesh(arrows) assert positions.shape[0] == colors.shape[0] > 0 def test_missing_contact_yields_no_arrow() -> None: assets = poc_scene() mapping = assets.surface_mapping assert mapping is not None arrows, _ = build_normal_overlay( contact_uv_xy=(1.0, 1.0), contact_found=False, contact_valid=True, fn=100.0, mapping=mapping, ) assert arrows.origins.shape[0] == 0