9fbdc3eInteractive hit-and-run sampling of a 2D convex regionJeremy Magland 1function hitandrun_sampler(N)
2%HITANDRUN_SAMPLER Interactive figure: hit-and-run sampling of a 2D convex region.
3% HITANDRUN_SAMPLER(N) generates a random convex polygon, draws N samples
4% from the uniform distribution on it using the hit-and-run algorithm, and
5% opens a figure that shows the region and the samples.
6%
7% This holds all the wiring: it builds the region, runs the sampler, loads
8% the prebuilt figure app, and sends region + samples to it (script ->
9% figure). It also re-samples on request (figure -> script) so the controls
10% in the figure drive the algorithm.
11%
12% The region/sampling algorithm lives in helpers/ (make_region, hit_and_run);
13% the end-user script (hitandrun_demo.m) puts that folder on the path with
14% `addpath('helpers')` and calls this. Run hitandrun_demo.m, not this file
15% directly, so the path is set up.
16%
17% The script is a stateless sampling service: the figure owns the current
18% region and sends it back with each resample request, so there is no
19% server-side state to keep in sync across callbacks.
21if nargin < 1 || isempty(N)
22 N = 1500;
23end
25% Build a random convex region and draw N uniform samples from it.
26[vx, vy] = make_region();
27tic;
28[sx, sy] = hit_and_run(vx, vy, N, 50);
29fprintf('hit_and_run: N=%d sampled in %.3f s\n', N, toc);
31% The figure app is the prebuilt single-file page, relative to the project root
32% (the current working directory when a top-level script is run).
33html = fileread(fullfile('app', 'dist', 'index.html'));
35fig = figure;
36gl = uigridlayout(fig, [1 1], 'Padding', [0 0 0 0], ...
37 'RowHeight', {'1x'}, 'ColumnWidth', {'1x'});
38uihtml(gl, 'HTMLSource', html, 'Data', pack_data(vx, vy, sx, sy, N), ...
39 'HTMLEventReceivedFcn', @(src, ev) on_event(src, ev));
40end
42function on_event(src, ev)
43% Figure -> script. Two requests the controls send:
44% 'resample' {n, x, y} -> draw n fresh samples in the given region; reply
45% with a 'samples' event (region is unchanged).
46% 'newRegion' {n} -> build a new region, draw n samples in it; reply
47% with a full 'data' event (region + samples).
48d = ev.HTMLEventData;
49n = 10000;
50if isstruct(d) && isfield(d, 'n')
51 n = max(1, round(d.n));
52end
53switch ev.HTMLEventName
54 case 'resample'
55 vx = d.x(:);
56 vy = d.y(:);
57 tic;
58 [sx, sy] = hit_and_run(vx, vy, n, 50);
59 fprintf('resample: N=%d sampled in %.3f s\n', n, toc);
60 sendEventToHTMLSource(src, 'samples', pack_samples(sx, sy, n));
61 case 'newRegion'
62 [vx, vy] = make_region();
63 tic;
64 [sx, sy] = hit_and_run(vx, vy, n, 50);
65 fprintf('newRegion: N=%d sampled in %.3f s\n', n, toc);
66 sendEventToHTMLSource(src, 'data', pack_data(vx, vy, sx, sy, n));
67end
68end
70function data = pack_data(vx, vy, sx, sy, N)
71%PACK_DATA Full payload (region + samples) sent once when the figure opens.
72data = struct();
73data.type = 'hitandrun';
74data.region = struct('x', vx(:).', 'y', vy(:).');
75data.samples = struct('x', sx(:).', 'y', sy(:).');
76data.n = N;
77end
79function s = pack_samples(sx, sy, N)
80%PACK_SAMPLES Just the samples, sent on a resample (region is unchanged).
81s = struct('x', sx(:).', 'y', sy(:).', 'n', N);
82end