concept-collection / hitandrun-interactive
hitandrun-interactive / CLAUDE.md
7.7 KBPreviewCodeBlameHistoryRaw

CLAUDE.md#

Tips for future agents working in this repo. Patterned after the sibling surfacefun-interactive project (same numbl + uihtml two-way bridge), but the figure is a 2D canvas instead of a three.js surface.

Architecture#

Multi-file layout / addpath#

hitandrun_demo.m is the driver; its first statement is addpath('helpers') so make_region / hit_and_run resolve from the subdir. Two constraints make that placement mandatory:

This works the same in the browser deploy (the worker runs the interpreter, which honors the runtime addpath).

Data flow#

MATLAB → figure: set uihtml(..., 'Data', struct) or call sendEventToHTMLSource(src, 'eventName', data)

Figure → MATLAB: call sendToMATLAB('eventName', value) (see bridge.ts); receive via HTMLEventReceivedFcn

The demo, built in stages (all done)#

  1. (done) Generate a convex region + N hit-and-run samples in the script; show region + samples in the figure. The samples are drawn server-side and sent via Data.
  2. (done) Add controls to the figure panel: a Samples slider, a Resample button, and a New region button.
  3. (done) Wire those controls to the sampler (two-way bridge).
  4. (done) Non-convex regions. A non-convex region checkbox switches to a dumbbell — two convex bulbs joined by a narrow tube (make_region(false)), sampled by hit_and_run_general; the movie draws the multiple in-region segments a line makes through it. The dumbbell is non-star-shaped and need not contain the origin, so the general sampler seeds itself with an interior point found by rejection.
  5. (done) Local vs. union sampling. A local segment only checkbox (shown only when non-convex) switches hit_and_run_general between sampling the union of all in-region segments (default; uniform) and only the segment through the current point (local; non-uniform). It drives both the sampler and the movie overlay (regionSegments's localOnly).

The figure → script protocol (each request carries convex, plus local for non-convex regions):

hitandrun_sampler.m's sample_region(vx, vy, n, convex, local) dispatches to hit_and_run (convex, JIT) or hit_and_run_general(..., local) (non-convex, interpreter). The non-convex path can't JIT (sort + point-in-polygon), so App.tsx caps its N lower via SAMPLE_CHOICES_NONCONVEX. local only applies to non-convex regions (App.tsx: useLocal = nonConvex && local); toggling it resamples the same region.

Ideas for the next iteration: show the chain path / burn-in, or animate the walk.

Client-side vs. server-side interactivity#

Key files#

File Purpose
app/src/App.tsx Main React component; reads data, hosts the panel, non-convex + local toggles, movie regionSegments
app/src/render/RegionView.tsx 2D canvas renderer (region outline + sample dots + movie segments)
app/src/bridge.ts onData / onHostEvent / sendToMATLAB helpers (generic; identical across these projects)
hitandrun_sampler.m Opens the figure, sends data, handles resample/newRegion (figure plumbing: on_event, sample_region, pack_data, pack_samples)
helpers/make_region.m Random region — convex polygon on an ellipse (no convhull, so the auto-running figure view doesn't race the qhull backend load), or make_region(false) for a dumbbell (two disks + narrow tube)
helpers/hit_and_run.m Convex hit-and-run sampler (half-plane chord intersection; JIT)
helpers/hit_and_run_general.m Non-convex hit-and-run sampler (union of all in-region segments, or local = only the one through the current point; interpreter)
hitandrun_demo.m User-facing driver: addpath('helpers') + seed + call the sampler

Local iteration#

Always rebuild the figure app first — both workflows read the prebuilt app/dist/index.html:

cd app && npm install && npm run build      # produces app/dist/index.html
cd ..

NUMBL below is a local clone of https://github.com/flatironinstitute/numbl (e.g. ~/src/numbl). Run its CLI with npx tsx $NUMBL/src/cli.ts … — no global install.

A. Quick run via the CLI (fastest inner loop)#

npx tsx $NUMBL/src/cli.ts run hitandrun_demo.m --plot

--plot opens the figure in a browser and keeps the script's session alive so figure → script callbacks work (Ctrl+C to stop). Good for iterating on the .m

B. Preview the actual GitHub Pages site locally#

This reproduces what the deploy workflow ships (it calls flatironinstitute/numbl/.github/actions/build-site@main, which is just cli.ts build-site after building the site-viewer). The numbl in the deployed site runs the .m in a web worker in the browser, and it keeps a live uihtml session there — so figure → script callbacks (resample) round-trip in the deployed site exactly like in the CLI --plot path. (That two-way bridge is why the workflow builds numbl from main rather than the npm release.)

# one-time, in the numbl clone: build the browser site-viewer
( cd $NUMBL && npm ci && npm run build:site-viewer )

# from this project: bundle project + viewer into _site/
npx tsx $NUMBL/src/cli.ts build-site . --out _site --base /

# serve it (localhost is a secure context, so coi-serviceworker.js can set the
# COOP/COEP headers numbl's WASM needs)
( cd _site && python3 -m http.server 8080 )
# → open http://localhost:8080/

Notes: