function hitandrun_sampler(N) %HITANDRUN_SAMPLER Interactive figure: hit-and-run sampling of a 2D convex region. % HITANDRUN_SAMPLER(N) generates a random convex polygon, draws N samples % from the uniform distribution on it using the hit-and-run algorithm, and % opens a figure that shows the region and the samples. % % This holds all the wiring: it builds the region, runs the sampler, loads % the prebuilt figure app, and sends region + samples to it (script -> % figure). It also re-samples on request (figure -> script) so the controls % in the figure drive the algorithm. % % The region/sampling algorithm lives in helpers/ (make_region, hit_and_run); % the end-user script (hitandrun_demo.m) puts that folder on the path with % `addpath('helpers')` and calls this. Run hitandrun_demo.m, not this file % directly, so the path is set up. % % The script is a stateless sampling service: the figure owns the current % region and sends it back with each resample request, so there is no % server-side state to keep in sync across callbacks. if nargin < 1 || isempty(N) N = 1500; end % Build a random convex region and draw N uniform samples from it. [vx, vy] = make_region(); tic; [sx, sy] = hit_and_run(vx, vy, N, 50); fprintf('hit_and_run: N=%d sampled in %.3f s\n', N, toc); % The figure app is the prebuilt single-file page, relative to the project root % (the current working directory when a top-level script is run). html = fileread(fullfile('app', 'dist', 'index.html')); fig = figure; gl = uigridlayout(fig, [1 1], 'Padding', [0 0 0 0], ... 'RowHeight', {'1x'}, 'ColumnWidth', {'1x'}); uihtml(gl, 'HTMLSource', html, 'Data', pack_data(vx, vy, sx, sy, N), ... 'HTMLEventReceivedFcn', @(src, ev) on_event(src, ev)); end function on_event(src, ev) % Figure -> script. Two requests the controls send: % 'resample' {n, x, y} -> draw n fresh samples in the given region; reply % with a 'samples' event (region is unchanged). % 'newRegion' {n} -> build a new region, draw n samples in it; reply % with a full 'data' event (region + samples). d = ev.HTMLEventData; n = 10000; if isstruct(d) && isfield(d, 'n') n = max(1, round(d.n)); end switch ev.HTMLEventName case 'resample' vx = d.x(:); vy = d.y(:); tic; [sx, sy] = hit_and_run(vx, vy, n, 50); fprintf('resample: N=%d sampled in %.3f s\n', n, toc); sendEventToHTMLSource(src, 'samples', pack_samples(sx, sy, n)); case 'newRegion' [vx, vy] = make_region(); tic; [sx, sy] = hit_and_run(vx, vy, n, 50); fprintf('newRegion: N=%d sampled in %.3f s\n', n, toc); sendEventToHTMLSource(src, 'data', pack_data(vx, vy, sx, sy, n)); end end function data = pack_data(vx, vy, sx, sy, N) %PACK_DATA Full payload (region + samples) sent once when the figure opens. data = struct(); data.type = 'hitandrun'; data.region = struct('x', vx(:).', 'y', vy(:).'); data.samples = struct('x', sx(:).', 'y', sy(:).'); data.n = N; end function s = pack_samples(sx, sy, N) %PACK_SAMPLES Just the samples, sent on a resample (region is unchanged). s = struct('x', sx(:).', 'y', sy(:).', 'n', N); end