Skip to content

Add a slice control to show only atoms within a slab - #452

Merged
andeplane merged 4 commits into
mainfrom
claude/issue-71-slice
Oct 16, 2026
Merged

andeplane merged 4 commits into
mainfrom
claude/issue-71-slice

Conversation

@andeplane

@andeplane andeplane commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

Requested by Anders Hafreager · project thread

Before: there was no way to see inside a bulk system; interior features like crack tips and defects were always hidden behind the surface.

After: a "Slice" button on the run screen opens a small panel with a plane normal (x, y, z or a custom vector), a position, a width and an invert option. Only whole atoms inside the slab are drawn, and bonds with an end outside it are hidden too. The slab follows the running simulation and updates immediately when moved, also while paused. With it off, rendering is unchanged.

How: a new SliceModifier, registered in EngineRegistry.createDefaultModifiers() after Colors and included in the rendering-only pass, hides atoms by setting their per-atom radius to zero through particleAttributes.ts; the picking shader reads the same radius, so hidden atoms can't be clicked and visible ones still pick the right ID. Clipping planes were rejected because they cut spheres in half and don't hide bonds. Only slots whose hidden state changed are rewritten on the GPU, and switching off restores radii once. The slice is turned off in runHost.beginFreshRun (not on continuations), since its position is in absolute box units. The Slice button sits in RunDetailHeader next to "Color atoms", and its popover picks left or right alignment from the space available so it never pushes the run column into a horizontal scroll. Unit tests cover slab selection (axes, custom and tilted normals, edges, invert), hiding and restoring atoms and bonds, the box-range helper including triclinic boxes, the popover alignment choice and the fresh-run reset. Checked in Chromium on a 216-atom lattice with 540 bonds: every atom's and bond's radius matched the slab for z, invert, moving the slab while running and while paused, and switching off; the popover stayed inside the run column at 900–1440 px.

Merge note: the slice tests drawn positions per draw slot rather than LAMMPS atom indices, so it also slices the periodic image copies from #449 (appended inside the Particles step, before Slice). Both PRs change src/rendering/particleAttributes.ts and the modifier list in EngineRegistry, so whichever merges second needs those reconciled: hidden flags are per slot here, while #449 makes per-ID styles reach every copy.

Known limitations: the panel closes on any click outside it (including dragging the view); position/width are in absolute box units with a ±50 slider fallback before the box is known; below roughly 800 px the run column is narrower than the panel.

Closes #71

🤖 Generated with Claude Code

https://claude.ai/code/session_01HB39E3Y4jpon2ijSXT7emN

A new SliceModifier hides every atom outside a slab defined by a plane
normal (x, y, z or a custom vector), a position along it, a width and an
invert option. It is visual only: hidden atoms are drawn with zero radius
through the existing per-instance radius attribute, so whole atoms vanish
from both drawing and GPU picking while counts, IDs and per-atom data stay
untouched. Bonds with a hidden end are hidden the same way. It runs after
Particles/Bonds/Colors in both post-timestep passes, so it follows the
simulation and re-applies immediately when the slab moves while paused.
When off it does nothing, after restoring radii once.

The run detail gets a compact "Slice" popover next to "Color atoms".
The slice is switched off for a new simulation, since the slab is in
absolute coordinates.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HB39E3Y4jpon2ijSXT7emN
@andeplane andeplane self-assigned this Oct 16, 2026
@andeplane
andeplane marked this pull request as ready for review October 16, 2026 07:19
Brings the slice modifier up to date with main's engine/store refactors
(#455-#462). Conflicts and how they were resolved:

- src/store/processing.ts: took main's version (modifier list moved to
  EngineRegistry); re-added SliceModifier to the rendering-only filter over
  engine.modifiers.
- src/store/simulation.ts: took main's version (newSimulation/run moved to
  RunController/runHost); the "slice off on a new simulation" reset now lives
  in runHost.beginFreshRun next to the color-modifier reset.
- src/shell/RunDetail.tsx: took main's version (split into RunDetailHeader,
  RunViewport, ...); the Slice button now renders in RunDetailHeader after
  "Color atoms", under the same live/viewStructure condition.

Other ports: SliceModifier is in createDefaultModifiers right after Colors;
SliceControls finds it via useEngine().modifiers; Popover's align prop
auto-merged into src/shell/ui/controls.tsx; particleAttributes merged
cleanly. Added a runHost test for the slice being switched off.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HB39E3Y4jpon2ijSXT7emN
The popover was always left-aligned to the Slice button, so with the
button near the right end of the header (e.g. a live run in a 1280 px
window) it ran past the column's clipping edge and scrolled the column
sideways by ~95 px. It now lines up with whichever button edge keeps it
inside the nearest overflow-clipping ancestor (left when it fits, else
right, else the roomier side), measured before paint on open and on
toggling, since the "Slice on" label can re-wrap the header.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HB39E3Y4jpon2ijSXT7emN
Hidden flags stay per slot while per-ID styles now reach every periodic
image, so setRadius keeps hidden copies at zero. The custom-normal inputs
keep a text draft so clearing the field or typing a minus sign no longer
commits 0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HB39E3Y4jpon2ijSXT7emN
@andeplane
andeplane merged commit df3afbb into main Oct 16, 2026
3 checks passed
@andeplane
andeplane deleted the claude/issue-71-slice branch October 16, 2026 14:19
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.

Add a slice modifier

2 participants