XIAN-FEM-2026June/3D opticsfem-master/compare/build_z_slice.m

126 lines
2.6 KiB
Matlab

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<AGROW>
xs = [xs; poly(tris(t, :), ia)]; %#ok<AGROW>
ys = [ys; poly(tris(t, :), ib)]; %#ok<AGROW>
vals = [vals; localVals(tris(t, :))]; %#ok<AGROW>
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<AGROW>
elseif abs(cb - coord) < tol
pts = [pts; V(b, :)]; %#ok<AGROW>
elseif (ca - coord) * (cb - coord) < 0
t = (coord - ca) / (cb - ca);
pts = [pts; V(a, :) + t * (V(b, :) - V(a, :))]; %#ok<AGROW>
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<AGROW>
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