# Interactive hit-and-run sampling Runs in the browser via [numbl](https://numbl.org) — no install. ## 🎛 [Just the figure →](https://concept-collection.github.io/hitandrun-interactive/#figure/sampler) The figure-only view runs the sampler and drops you straight into the interactive figure (it shows the run's output first, then the figure). The full developer view — file tree, editable code, console — is below. ## ▶ [Open `hitandrun_demo.m`](hitandrun_demo.m) and click **Run** A random 2D region is generated and `N` points are drawn uniformly from it by **hit-and-run**: from the current point, pick a random direction, take the chord where that line crosses the region, and jump to a uniform point on it. Repeat. The figure shows the region and the samples. The region is convex by default, but you can switch to a non-convex (star-shaped) one, where a single line can enter and leave the region several times. Controls: - **Samples** — set `N` (re-runs the sampler). - **Resample** — new samples, same region. - **New region** — a fresh region (of the current type). - **non-convex region** — toggle between a convex region and a non-convex star-shaped one. The non-convex region uses the slower general sampler, so `N` is capped lower. - **Play movie** — step through the algorithm: each step draws the chord — one segment for a convex region, possibly several for a non-convex one — and the point that landed on it. ## How it works - [`hitandrun_demo.m`](hitandrun_demo.m) — driver: `addpath('helpers')`, seed, call the sampler. - [`hitandrun_sampler.m`](hitandrun_sampler.m) — opens the figure, sends data, handles resample requests, and dispatches to the convex or non-convex sampler. - `helpers/` — [`make_region.m`](helpers/make_region.m) (convex or star region), [`hit_and_run.m`](helpers/hit_and_run.m) (convex chord), and [`hit_and_run_general.m`](helpers/hit_and_run_general.m) (arbitrary simple polygon). - `app/` — a single-file React app that draws the region and samples on a canvas. The script and figure talk both ways: the script sends the region + samples via `uihtml(..., 'Data', ...)`, and the controls call back with `sendToMATLAB('resample' | 'newRegion', ...)` (each carrying whether the region is `convex`), which re-runs the sampler and returns new points via `sendEventToHTMLSource`. The script is stateless — the figure owns the region and passes it back with each request. ## Convex vs. non-convex `hitandrun_sampler.m` picks the sampler by region type: - **Convex** — [`hit_and_run.m`](helpers/hit_and_run.m) takes the single chord where the line crosses the region (an inward-half-plane intersection). Its loop runs once per sample, so numbl JS-JIT-compiles it to JavaScript — about 30× faster than its interpreter, which is what keeps large `N` instant. The `%!numbl:assert_jit` directive asserts this happens (it errors rather than silently falling back). It relies on numbl's scalar-`rand()` JIT support; `rng(seed)` still controls the shared PRNG. - **Non-convex** — [`hit_and_run_general.m`](helpers/hit_and_run_general.m) finds *every* crossing along the line, keeps the segments whose midpoint is inside (a point-in-polygon test), and samples uniformly across their union, so concavities are handled correctly. The sort + polygon tests don't JIT, so this runs in the interpreter and `N` is capped lower. `make_region(false)` builds a star polygon that is star-shaped about the origin, so the origin is a valid interior start point. ## Deploy Pushing to `main` builds the app and publishes the project to GitHub Pages via the [deploy workflow](.github/workflows/deploy.yml).