/ concept-collection / hitandrun-interactive
Sign in
concept-collection / hitandrun-interactive
hitandrun-interactive / CLAUDE.md
156 lines · 7.5 KBCodeBlameHistory
3Tips for future agents working in this repo. Patterned after the sibling
4`surfacefun-interactive` project (same numbl + uihtml two-way bridge), but the
5figure is a 2D canvas instead of a three.js surface.
7## Architecture
9- `app/` — React single-file widget (`npm run build``app/dist/index.html`)
10- `*.m` at root — scripts users open and run in [numbl](https://numbl.org)
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 11- `helpers/` — the region/sampling algorithm (`make_region`, `hit_and_run`,
12 `hit_and_run_general`), put on the path by the driver via `addpath('helpers')`
13- `numbl-project.json` — project metadata; `entry` is the landing page. Its
14 `figures` array declares the editor-less figure view the deploy exposes at
15 `#figure/sampler` (runs `hitandrun_demo.m`, shows just the interactive figure);
16 the org profile's "live" link points there.
18### Multi-file layout / addpath
20`hitandrun_demo.m` is the **driver**; its first statement is
21`addpath('helpers')` so `make_region` / `hit_and_run` resolve from the subdir.
22Two constraints make that placement mandatory:
24- `addpath(<literal>)` must be a **leading** statement in the driver, before any
25 other non-comment statement (numbl's static path resolution requires it; the
26 runtime/interpreter path is fine with it too). It also cannot live inside a
27 function file — only the driver. So `hitandrun_sampler.m` can't add the path
28 itself; run `hitandrun_demo.m`, not the sampler directly.
29- Plain subdirectories are otherwise invisible to function resolution — only
30 `addpath`'d dirs (plus root, `+pkg`, `@Class`, `private/`) are searched.
32This works the same in the browser deploy (the worker runs the interpreter,
33which honors the runtime `addpath`).
35## Data flow
37**MATLAB → figure:** set `uihtml(..., 'Data', struct)` or call
38`sendEventToHTMLSource(src, 'eventName', data)`
40**Figure → MATLAB:** call `sendToMATLAB('eventName', value)` (see `bridge.ts`);
41receive via `HTMLEventReceivedFcn`
43## The demo, built in stages (all done)
451. **(done)** Generate a convex region + `N` hit-and-run samples in the script;
46 show region + samples in the figure. The samples are drawn server-side and
47 sent via `Data`.
482. **(done)** Add controls to the figure panel: a **Samples** slider, a
49 **Resample** button, and a **New region** button.
503. **(done)** Wire those controls to the sampler (two-way bridge).
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 514. **(done)** Non-convex regions. A **non-convex region** checkbox switches to a
52 star polygon (`make_region(false)`) sampled by `hit_and_run_general`; the
53 movie draws the multiple in-region segments a line makes through it.
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 545. **(done)** Local vs. union sampling. A **local segment only** checkbox (shown
55 only when non-convex) switches `hit_and_run_general` between sampling the
56 union of all in-region segments (default; uniform) and only the segment
57 through the current point (local; non-uniform). It drives both the sampler
58 and the movie overlay (`regionSegments`'s `localOnly`).
60The figure → script protocol (each request carries `convex`, plus `local` for
61non-convex regions):
63- **Samples** slider (on release) / **Resample** / **local** toggle →
64 `sendToMATLAB('resample', { n, x, y, convex, local })`. `x, y` are the
65 *current region's* vertices — the script is **stateless**, so it samples the
66 region it is given and replies with `sendEventToHTMLSource(src, 'samples', {
67 x, y, n })`.
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 68- **New region** / **non-convex** toggle → `sendToMATLAB('newRegion', { n,
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 69 convex, local })`. The script builds a new region of that type and replies with
70 a full `sendEventToHTMLSource(src, 'data', <payload>)` (same shape as the
71 initial `Data`, plus `convex`).
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 73`hitandrun_sampler.m`'s `sample_region(vx, vy, n, convex, local)` dispatches to
74`hit_and_run` (convex, JIT) or `hit_and_run_general(..., local)` (non-convex,
75interpreter). The non-convex path can't JIT (sort + point-in-polygon), so
76`App.tsx` caps its `N` lower via `SAMPLE_CHOICES_NONCONVEX`. `local` only applies
77to non-convex regions (`App.tsx`: `useLocal = nonConvex && local`); toggling it
78resamples the same region.
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 80Ideas for the next iteration: show the chain path / burn-in, or animate the
81walk.
83## Client-side vs. server-side interactivity
85- **Low-latency / view-only** (e.g. dot size, zoom): update React state only —
86 instant, no MATLAB round-trip.
87- **New samples** (depends on the RNG and the algorithm): `sendToMATLAB`
88 script re-runs → `sendEventToHTMLSource` → React re-renders.
90## Key files
92| File | Purpose |
93|------|---------|
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 94| `app/src/App.tsx` | Main React component; reads data, hosts the panel, non-convex + local toggles, movie `regionSegments` |
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 95| `app/src/render/RegionView.tsx` | 2D canvas renderer (region outline + sample dots + movie `segments`) |
9fbdc3eInteractive hit-and-run sampling of a 2D convex regionJeremy Magland 96| `app/src/bridge.ts` | `onData` / `onHostEvent` / `sendToMATLAB` helpers (generic; identical across these projects) |
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 97| `hitandrun_sampler.m` | Opens the figure, sends data, handles `resample`/`newRegion` (figure plumbing: `on_event`, `sample_region`, `pack_data`, `pack_samples`) |
fcc5958Generate convex region without convhull (fixes figure-view startup race)Jeremy Magland 98| `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 star polygon |
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 99| `helpers/hit_and_run.m` | Convex hit-and-run sampler (half-plane chord intersection; JIT) |
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 100| `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) |
9fbdc3eInteractive hit-and-run sampling of a 2D convex regionJeremy Magland 101| `hitandrun_demo.m` | User-facing driver: `addpath('helpers')` + seed + call the sampler |
103## Local iteration
105Always rebuild the figure app first — both workflows read the prebuilt
106`app/dist/index.html`:
108```
109cd app && npm install && npm run build # produces app/dist/index.html
110cd ..
111```
113`NUMBL` below is a local clone of https://github.com/flatironinstitute/numbl
114(e.g. `~/src/numbl`). Run its CLI with `npx tsx $NUMBL/src/cli.ts …` — no
115global install.
117### A. Quick run via the CLI (fastest inner loop)
119```
120npx tsx $NUMBL/src/cli.ts run hitandrun_demo.m --plot
121```
123`--plot` opens the figure in a browser and keeps the script's session alive so
124figure → script callbacks work (Ctrl+C to stop). Good for iterating on the `.m`
125+ app together.
127### B. Preview the actual GitHub Pages site locally
129This reproduces what the [deploy workflow](.github/workflows/deploy.yml) ships
130(it calls `flatironinstitute/numbl/.github/actions/build-site@main`, which is
131just `cli.ts build-site` after building the site-viewer). The numbl in the
132deployed site runs the `.m` in a **web worker in the browser**, and it keeps a
133live uihtml session there — so figure → script callbacks (`resample`) round-trip
134in the deployed site exactly like in the CLI `--plot` path. (That two-way bridge
135is why the workflow builds numbl from `main` rather than the npm release.)
137```
138# one-time, in the numbl clone: build the browser site-viewer
139( cd $NUMBL && npm ci && npm run build:site-viewer )
141# from this project: bundle project + viewer into _site/
142npx tsx $NUMBL/src/cli.ts build-site . --out _site --base /
144# serve it (localhost is a secure context, so coi-serviceworker.js can set the
145# COOP/COEP headers numbl's WASM needs)
146( cd _site && python3 -m http.server 8080 )
147# → open http://localhost:8080/
148```
150Notes:
151- `--base /` is for serving at localhost root. GitHub Pages serves this project
152 at `/<repo>/`, so the workflow auto-detects `--base /hitandrun-interactive/`.
153 Content is identical; only asset paths differ.
154- `_site/` and `dist/` are git-ignored (see `.gitignore`).
155- The real target is GitHub Pages, where the same single-file app runs against
156 numbl compiled in the browser.
moveopenescclose