Interactive hit-and-run sampling#
Runs in the browser via numbl β no install.
π Just the figure β#
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 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
Nis 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β driver:addpath('helpers'), seed, call the sampler.hitandrun_sampler.mβ opens the figure, sends data, handles resample requests, and dispatches to the convex or non-convex sampler.helpers/βmake_region.m(convex or star region),hit_and_run.m(convex chord), andhit_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.mtakes 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 largeNinstant. The%!numbl:assert_jitdirective 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.mfinds 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 andNis 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.