function slice = build_z_slice(mesh, field, z0, axis) %BUILD_Z_SLICE Cut 3D tet mesh by plane and sample scalar field on slice. % axis: 1=x, 2=y, 3=z (default 3) if nargin < 4 axis = 3; end if axis == 1 ia = 2; ib = 3; elseif axis == 2 ia = 1; ib = 3; else ia = 1; ib = 2; end xs = []; ys = []; vals = []; elems = []; nodeCount = 0; tol = 1e-9; for n = 1:mesh.NbrTet tet = mesh.Tet(n, :); V = mesh.Vertex(tet, :); poly = tetPlanePoly(V, axis, z0, tol); if isempty(poly) continue; end localVals = zeros(size(poly, 1), 1); for p = 1:size(poly, 1) localVals(p) = interpTetScalar(poly(p, :), tet, mesh.Vertex, field); end tris = polyToTris(size(poly, 1)); for t = 1:size(tris, 1) idx = tris(t, :) + nodeCount; elems = [elems; idx]; %#ok xs = [xs; poly(tris(t, :), ia)]; %#ok ys = [ys; poly(tris(t, :), ib)]; %#ok vals = [vals; localVals(tris(t, :))]; %#ok nodeCount = nodeCount + 3; end end slice.x = xs; slice.y = ys; slice.val = vals; slice.elem = elems; slice.planeAxes = [ia, ib]; slice.z0 = z0; end function poly = tetPlanePoly(V, axis, coord, tol) c = V(:, axis); if coord < min(c) - tol || coord > max(c) + tol poly = []; return; end if all(abs(c - coord) < 1e-6) idx = find(abs(c - coord) < 1e-6); if numel(idx) >= 3 poly = V(idx(1:3), :); else poly = []; end return; end edges = [1 2; 1 3; 1 4; 2 3; 2 4; 3 4]; pts = []; for e = 1:size(edges, 1) a = edges(e, 1); b = edges(e, 2); ca = c(a); cb = c(b); if abs(ca - coord) < tol pts = [pts; V(a, :)]; %#ok elseif abs(cb - coord) < tol pts = [pts; V(b, :)]; %#ok elseif (ca - coord) * (cb - coord) < 0 t = (coord - ca) / (cb - ca); pts = [pts; V(a, :) + t * (V(b, :) - V(a, :))]; %#ok end end if size(pts, 1) < 3 poly = []; return; end uniq = pts(1, :); for i = 2:size(pts, 1) d = sqrt(sum((pts(i, :) - uniq).^2, 2)); if all(d > 1e-8) uniq = [uniq; pts(i, :)]; %#ok end end if size(uniq, 1) < 3 poly = []; elseif size(uniq, 1) > 4 poly = uniq(1:4, :); else poly = uniq; end end function tris = polyToTris(n) if n == 3 tris = [1 2 3]; elseif n == 4 tris = [1 2 3; 1 3 4]; else tris = []; end end function val = interpTetScalar(p, tet, Vertex, field) V = Vertex(tet, :); f = field(tet); A = [V(2, :) - V(1, :); V(3, :) - V(1, :); V(4, :) - V(1, :)]'; w123 = A \ (p(:) - V(1, :)'); w0 = 1 - sum(w123); w = [w0; w123(:)]; val = sum(w .* f(:)); end