Skip to content

APP-16361 measurement and polyline improvements#743

Open
Devin T. Currie (DTCurrie) wants to merge 6 commits into
app-16292/5-gizmo-docsfrom
app-16361-measurement-and-polyline-improvements
Open

APP-16361 measurement and polyline improvements#743
Devin T. Currie (DTCurrie) wants to merge 6 commits into
app-16292/5-gizmo-docsfrom
app-16361-measurement-and-polyline-improvements

Conversation

@DTCurrie

Copy link
Copy Markdown
Member

Improves the measurement workflow with three additions: persistent measurements that can be hidden and deleted, draggable polyline vertices for measuring in empty space, and fixed-increment snapping in both measurement tools.

Frontend

  • src/lib/quantize.ts (new): shared quantize(point, step) that rounds a Vector3 to a uniform grid. Lifted to the lib root so both <MeasureTool /> and the Gizmos plugin can use it without depending on each other.
  • MeasureTool.svelte: when settings.snapping is on, quantizes the hit point to a 0.1 m grid before applying the existing per-axis lock, so locked axes still pin to the first point's exact value while unlocked axes snap to the grid.
  • LineTool.svelte (Gizmos): extends getCursorPosition to grid-quantize the hit when no vertex-to-vertex snap matches. GRID_SNAP_STEP = 0.1 matches the translationSnap used by SelectedTransformControls.
  • useSelectedPolylineVertex.svelte.ts (new, Gizmos): Svelte context holding { entity, index } | undefined for the currently picked polyline vertex. Provided at the root of Gizmos.svelte.
  • PolylineVertexHandles.svelte (new, Gizmos): pickable sphere at each vertex of the selected polyline gizmo. Click sets the vertex context, with event.stopPropagation() so the selection plugin does not fire alongside.
  • PolylineVertexTransformControls.svelte (new, Gizmos): proxy Object3D mounted at the picked vertex's world position with a TransformControls bound to it. On objectChange, transforms the proxy's world position back to entity-local via inverse(WorldMatrix) and writes into LinePositions. The proxy-reset effect tracks only the vertex selection (with untrack around LinePositions) so it does not fight TransformControls during a drag.
  • PolylineVertexEditor.svelte (new, Gizmos): coordinator that mounts handles and transform controls when the selected entity has Gizmo + LinePositions, is not PendingGizmo, and is not inherited-invisible. Auto-clears the vertex context when the selected entity changes or becomes non-editable.
  • PolylineMeasureDetails.svelte (new, Gizmos): details-panel List (Off / Per segment / Total length) that adds, sets, or removes the PolylineMeasure trait on the entity, so users can switch measurement mode after placement without redoing the polyline.
  • Gizmos.svelte: calls provideSelectedPolylineVertex(), mounts <PolylineVertexEditor /> below <GizmoEntities />.
  • GizmoDetails.svelte: gates LineDetails, GeometryDetails, etc. by entity shape; mounts <PolylineMeasureDetails /> alongside <LineDetails /> for polyline gizmos.
  • docs/plugins/gizmos.mdx: Polyline section documents placement snap, a new "Editing vertices after placement" subsection covering the handle drag workflow, and a "Persistent measurements" subsection that cross-links to <MeasureTool /> for the ephemeral case.
  • docs/plugins/measure-tool.mdx: new "Increment snap" section, plus a Starlight Aside cross-linking to the Gizmos polyline gizmo for persistent multi-segment measurement.

Why?

Why keep <MeasureTool /> and <Gizmos /> as separate plugins instead of folding measurement into the polyline gizmo?

The two workflows are genuinely different. <MeasureTool /> is a one-click ruler for "what is the distance between these two surface points right now." The polyline gizmo with lineMeasure is for "leave this measurement in the scene for reference." Folding the first into the second would force consumers who just want a quick distance check to pull in the entire Gizmos plugin (popover, seven gizmo types, traits surface) and would replace a one-click UX with a popover, type-pick, mode-set sequence. Keeping them separate also lets the Gizmos plugin evolve its own details and pre-placement options independently of the lightweight measurement tool.

Why TransformControls on a proxy for empty-space measurement instead of a construction-plane fallback when the cursor misses geometry?

A construction-plane fallback (project onto a horizontal plane through the last point, say) requires us to guess which plane the user meant, and a wrong guess produces a wildly off measurement. Direct manipulation is unambiguous: place the initial vertex on any nearby surface, then drag any vertex into position via the transform gizmo. The gizmo's axis arrows already provide per-axis constraint and translationSnap already provides grid snap, so no new UI is needed for either.

Testing

Tests passing and manually tested.

@changeset-bot

changeset-bot Bot commented Jun 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 44ddc6a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@viamrobotics/motion-tools Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://viamrobotics.github.io/visualization/pr-preview/pr-743/

Built to branch gh-pages at 2026-06-03 14:30 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant