Skip to content

feat(views): draw reference lines independently of the crosshairs tool - #921

Merged
PaulHax merged 1 commit into
Kitware:mainfrom
PaulHax:reference-lines
Aug 16, 2026
Merged

feat(views): draw reference lines independently of the crosshairs tool#921
PaulHax merged 1 commit into
Kitware:mainfrom
PaulHax:reference-lines

Conversation

@PaulHax

@PaulHax PaulHax commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Cross-reference lines were drawn inside the crosshairs tool, so they only existed while that tool was active. Pull them out into a standalone feature that a setting can turn on persistently, and that the crosshairs tool borrows as its on-screen appearance while it is active.

Visibility is derived (enabled || crosshairs active) rather than snapshot and restored, which gives the auto-on/restore behavior with no extra state and covers press-and-hold temporary crosshairs for free.

The geometry is a general plane-plane intersection clipped to the image box in index space, not an axis-aligned special case, so oblique planes only need wiring into the peer enumeration later. The intersection direction is transformed by the linear part of worldToIndex: a direction is a vector, so it never wanted the translation, and recovering it by subtracting two transformed points collapsed to zero in float32 for nearly parallel planes. Peers come from the layout slots, so lines survive maximizing a view and no stale viewByID entry can produce a ghost line.

Each line breaks around every point where another drawn line crosses it, leaving 16px of clear space. Doing that as a screen-space pass over the projected segments keeps the gap decoupled from the crosshairs position, so it appears the same way in always-on mode.

The crosshairs tool keeps its slicing inside the image its view shows. The slice write used to hang off a watcher on the crosshair position in the active image's index space, so merely focusing another image's view slammed every view of the newly active image to wherever the crosshair had been left in the other one. The move now propagates from the interaction itself: the view widget reports which view the point was picked in, and the store resolves the image from that view, clamps the point in its index space and slices only the layout views showing it. That leaves the widget state with nothing image-specific to track, so the shared matrices and handle bounds go away with it.

The feature lives in src/referenceLines, following src/processing: a single public surface plus a pure layer of geometry, crossings and peer enumeration, with the boundary enforced by eslint import zones.

Behavior changes that come with the pull-out:

  • lines sit at the peers' rounded slice positions and step during a crosshairs drag instead of tracking the pointer continuously
  • lines no longer hide when a view's slice differs from the crosshair slice
  • no lines when there is no peer 2D view
image

https://youtu.be/0pFMbjRyXbA

@netlify

netlify Bot commented Aug 15, 2026

Copy link
Copy Markdown

Deploy Preview for volview-dev ready!

Name Link
🔨 Latest commit cd56bef
🔍 Latest deploy log https://app.netlify.com/projects/volview-dev/deploys/6a81da36f1aafb00087d3792
😎 Deploy Preview https://deploy-preview-921--volview-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@PaulHax
PaulHax force-pushed the reference-lines branch 2 times, most recently from da5e53c to 6b4cbee Compare August 16, 2026 15:34
Cross-reference lines were drawn inside the crosshairs tool, so they only
existed while that tool was active. Pull them out into a standalone feature
that a setting can turn on persistently, and that the crosshairs tool
borrows as its on-screen appearance while it is active.

Visibility is derived (enabled || crosshairs active) rather than snapshot
and restored, which gives the auto-on/restore behavior with no extra state
and covers press-and-hold temporary crosshairs for free.

The geometry is a general plane-plane intersection clipped to the image box
in index space, not an axis-aligned special case, so oblique planes only
need wiring into the peer enumeration later. The intersection direction is
transformed by the linear part of worldToIndex: a direction is a vector, so
it never wanted the translation, and recovering it by subtracting two
transformed points collapsed to zero in float32 for nearly parallel planes.
Peers come from the layout slots, so lines survive maximizing a view and no
stale viewByID entry can produce a ghost line.

Each line breaks around every point where another drawn line crosses it,
leaving 16px of clear space. Doing that as a screen-space pass over the
projected segments keeps the gap decoupled from the crosshairs position, so
it appears the same way in always-on mode.

The crosshairs tool keeps its slicing inside the image its view shows.
The slice write used to hang off a watcher on the crosshair position in the
active image's index space, so merely focusing another image's view slammed
every view of the newly active image to wherever the crosshair had been left
in the other one. The move now propagates from the interaction itself: the
view widget reports which view the point was picked in, and the store
resolves the image from that view, clamps the point in its index space and
slices only the layout views showing it. That leaves the widget state with
nothing image-specific to track, so the shared matrices and handle bounds go
away with it.

The feature lives in src/referenceLines, following src/processing: a single
public surface plus a pure layer of geometry, crossings and peer
enumeration, with the boundary enforced by eslint import zones.

Behavior changes that come with the pull-out:

- lines sit at the peers' rounded slice positions and step during a
  crosshairs drag instead of tracking the pointer continuously
- lines no longer hide when a view's slice differs from the crosshair slice
- no lines when there is no peer 2D view
@PaulHax
PaulHax added this pull request to the merge queue Aug 16, 2026
Merged via the queue into Kitware:main with commit 9b96273 Aug 16, 2026
8 checks passed
@PaulHax
PaulHax deleted the reference-lines branch August 16, 2026 15:56
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