126 lines
2.6 KiB
Matlab
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
|