function vector_field_viewer(dom) %VECTOR_FIELD_VIEWER Interactive figure showing a tangent vector field on a surface. % VECTOR_FIELD_VIEWER(DOM) opens a figure that renders a tangent vector % field on the surfacemesh DOM. The arrow scale can be adjusted with a % slider in the figure (purely client-side; no MATLAB callback needed). html = fileread(fullfile('app', 'dist', 'index.html')); data = build_data(dom); fig = figure; gl = uigridlayout(fig, [1 1], 'Padding', [0 0 0 0], ... 'RowHeight', {'1x'}, 'ColumnWidth', {'1x'}); uihtml(gl, 'HTMLSource', html, 'Data', data); end function data = build_data(dom) %BUILD_DATA Pack surface patches and a dense divergence-free tangent vector field. % Samples every collocation point across all patches. The field is the % stream-function field for F = xyz: % v = (x(y^2-z^2), y(z^2-x^2), z(x^2-y^2)) % It is automatically tangent to the unit sphere (v·n = 0) and % divergence-free. The flow has 8 vortex centres at the cube vertices and % 6 saddle points at the cube-face centres, producing eight distinct % swirling regions whose index sum satisfies the Poincare-Hopf theorem. np = length(dom); px = cell(1, np); py = cell(1, np); pz = cell(1, np); for k = 1:np px{k} = real(dom.x{k}(:).'); py{k} = real(dom.y{k}(:).'); pz{k} = real(dom.z{k}(:).'); end % Collect ALL collocation points across every patch. all_x = horzcat(px{:}); all_y = horzcat(py{:}); all_z = horzcat(pz{:}); % Stream-function vector field v = n x grad_S(xyz) on the unit sphere. uu = all_x .* (all_y.^2 - all_z.^2); vv = all_y .* (all_z.^2 - all_x.^2); ww = all_z .* (all_x.^2 - all_y.^2); data = struct(); data.type = 'vectorfield'; data.n = size(dom.x{1}, 1); data.x = px; data.y = py; data.z = pz; data.npatches = np; data.vectors = struct('x', all_x, 'y', all_y, 'z', all_z, 'u', uu, 'v', vv, 'w', ww); end