1function refine_demo
2%REFINE_DEMO Interactive surfacefun mesh refinement via a uihtml figure.
3%
4% Runs in the numbl IDE and via `numbl run --plot`. Shows a cubed-sphere
5% surfacemesh rendered with numbl's surface renderer (duplicated into the
6% bundled web app). Drag the "Refinement level" slider in the figure: the
7% page sends the level to this script, which refines the base mesh with
8% surfacefun and sends the new patches back — the figure re-renders without
9% losing the camera orientation.
10%
11% The web app is prebuilt into app/dist/index.html (cd app && npm run build).
13mip load --install flatironinstitute/flatironinstitute/surfacefun
15here = fileparts(mfilename('fullpath'));
16html = fileread(fullfile(here, 'app', 'dist', 'index.html'));
18maxLevel = 3; % slider range 0..maxLevel
19n = 8; % Chebyshev order per patch
20dom0 = surfacemesh.sphere(n); % base cubed sphere (6 patches)
22data0 = meshToData(dom0, 0, maxLevel);
24fig = figure;
25gl = uigridlayout(fig, [1 1], 'Padding', [0 0 0 0], ...
26 'RowHeight', {'1x'}, 'ColumnWidth', {'1x'});
27uihtml(gl, 'HTMLSource', html, 'Data', data0, ...
28 'HTMLEventReceivedFcn', @(src, ev) onRefine(src, ev, dom0, maxLevel));
29end
31function onRefine(src, ev, dom0, maxLevel)
32% Refine the base mesh to the requested absolute level and send it back.
33if ~strcmp(ev.HTMLEventName, 'refine')
34 return
35end
36level = max(0, min(maxLevel, round(ev.HTMLEventData)));
37if level == 0
38 dom = dom0;
39else
40 dom = refine(dom0, level);
41end
42sendEventToHTMLSource(src, 'mesh', meshToData(dom, level, maxLevel));
43fprintf('refined to level %d: %d patches\n', level, length(dom));
44end
46function data = meshToData(dom, level, maxLevel)
47% Pack a surfacemesh into a plain struct the web app can render: one flat
48% (column-major) x/y/z array per patch, each an n-by-n grid.
49np = length(dom);
50px = cell(1, np);
51py = cell(1, np);
52pz = cell(1, np);
53for k = 1:np
54 % real() drops any (all-zero) imaginary part the solver/JIT may carry;
55 % the geometry is real and jsonencode (numbl and MATLAB) rejects complex.
56 px{k} = real(dom.x{k}(:).');
57 py{k} = real(dom.y{k}(:).');
58 pz{k} = real(dom.z{k}(:).');
59end
60data = struct();
61data.n = size(dom.x{1}, 1);
62data.x = px;
63data.y = py;
64data.z = pz;
65data.npatches = np;
66data.level = level;
67data.maxLevel = maxLevel;
68end