Skip to content

Visualizer: add a background workcell grid with origin axes and edge fade - #1151

Merged
BioCam merged 3 commits into
PyLabRobot:mainfrom
BioCam:create-workcell-grid
Jul 6, 2026
Merged

Visualizer: add a background workcell grid with origin axes and edge fade#1151
BioCam merged 3 commits into
PyLabRobot:mainfrom
BioCam:create-workcell-grid

Conversation

@BioCam

@BioCam BioCam commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

The visualizer canvas draws the deck and its resources but offers no spatial reference. A scale bar gives the length of one round distance, but there is nothing to judge position, size, or alignment at a glance across the scene, and no visible marker for the coordinate origin the layout is built around.

  • Add a grey grid on its own bottom-most Konva layer, beneath every resource. It is a pure canvas overlay, not a Resource, so it never appears in the workcell tree and never touches deck or resource state.
  • Match the grid spacing to the scale bar: both derive their step from a shared niceScaleMM helper, so one grid cell always equals the scale-bar distance at any zoom.
  • Anchor the grid at the top-level resource's origin, so the origin always lies on a line, and draw a red x-axis line and green y-axis line through it that match the on-canvas axis arrows.
  • Draw the grid in world coordinates so it pans and zooms locked to the deck, and fade it out towards the edges of the view window with a radial vignette that dims only the grid, never the resources.
  • Give each deck (HamiltonSTARDeck, VantageDeck, OTDeck) an opaque footprint fill drawn behind its contents, so it paints its own surface and occludes the grid instead of relying on the global canvas background; the base Deck already fills its footprint.
  • Keep the grid nodes persistent and rebuild the lines only when the scale changes or the viewport drifts off the drawn extent, coalescing redraws to one per animation frame; a pan reuses the existing world-coordinate lines and moves only the single fade rect.

Behaviour: the grid is view-only - it adds no resource, changes no tree count, and alters no deck or resource state; only the canvas gains a background layer. Decks render as before except that their footprint now occludes the grid the same way the global background did previously, so nothing bleeds through the deck. Frontend only (lib.js); no Python or API change.

🤖 Generated with Claude Code

BioCam and others added 3 commits July 6, 2026 11:22
…e fade

Draw a grey (alpha 0.2) reference grid on its own bottom-most Konva layer,
beneath every resource. It is a pure canvas overlay, not a Resource, so it
never appears in the Workcell Tree.

- Spacing matches the scale bar: both share a new `niceScaleMM` helper.
- Anchored at the top-level resource's origin; the origin always lands on a line.
- Lines are in world-mm, so they pan and zoom locked to the deck; redrawn on
  zoom, fit, and a new pan (`dragmove`) handler to follow the viewport.
- A red x-axis line at y=0 and green y-axis line at x=0 match the axis arrows.
- A radial vignette fades the grid (and axes) out towards the view-window edges,
  affecting only the grid, never the resources.

Give each deck (`HamiltonSTARDeck`, `VantageDeck`, `OTDeck`) an opaque white
footprint fill drawn behind its contents, so it paints its own surface and
occludes the grid instead of relying on the global background; the base `Deck`
already fills its footprint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… changes

The grid previously destroyed and recreated every line node on each pan
(`dragmove`) and zoom event, allocating dozens-to-hundreds of Konva nodes and a
fresh gradient per pointer event. Two changes cut that to near-zero on pans:

- Coalesce redraws with requestAnimationFrame so a burst of dragmove/wheel
  events between frames triggers a single rebuild.
- Keep the grid nodes persistent and rebuild the lines only when the scale
  changes (zoom) or the viewport drifts off the drawn extent. Lines are drawn
  over the viewport snapped to whole cells plus a margin, so a pan reuses the
  existing world-mm lines (which pan with the stage) until it crosses the margin;
  only the single view-pinned vignette rect is moved each frame.

A sustained pan now costs one setAttrs plus a batchDraw per frame instead of a
full node teardown and rebuild.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fill each deck's footprint with a radial gradient - a slightly brighter centre
easing out to a light grey at the edges - so the surface reads as gently lit
rather than pure white against the canvas.

- The gradient is drawn in a unit square and stretched to the footprint by a
  non-uniform group scale, so the fade is an ellipse matching the deck's aspect
  ratio and reaches the edge evenly on a wide deck rather than pooling in a
  circle that only darkens at the corners.
- Both stops are opaque, so the deck still occludes the background grid; the
  rail box (`HamiltonSTARDeck`, `VantageDeck`) and the slots (`OTDeck`) are drawn
  stroke-only over the gradient so the fade stays continuous across the surface.
- Centre and edge shades live in shared `DECK_SURFACE_CENTER` / `DECK_SURFACE_EDGE`
  constants; the edge is a neutral grey (equal RGB channels, no tint).

Re-rasterized only when the deck is drawn (load, resource-state change, zoom),
not per pan frame, so it does not affect pan smoothness.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@BioCam
BioCam merged commit f7dfdd2 into PyLabRobot:main Jul 6, 2026
21 checks passed
@BioCam
BioCam deleted the create-workcell-grid branch July 6, 2026 11:30
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