|
| 1 | +function [r, cc] = circumradius(p, t) |
| 2 | +% |
| 3 | +% [r, cc] = circumradius(p, t) |
| 4 | +% Compute circumradius and circumcenter for triangles/tets |
| 5 | +% |
| 6 | +% Input: |
| 7 | +% p - Nx3 vertex coordinates |
| 8 | +% t - Mx3 (triangles) or Mx4 (tetrahedra) element connectivity |
| 9 | +% |
| 10 | +% Output: |
| 11 | +% r - Mx1 circumradius |
| 12 | +% cc - Mx3 circumcenter coordinates |
| 13 | + |
| 14 | +if size(t, 2) == 3 % Triangular mesh |
| 15 | + % Get triangle vertices |
| 16 | + v1 = p(t(:, 1), :); |
| 17 | + v2 = p(t(:, 2), :); |
| 18 | + v3 = p(t(:, 3), :); |
| 19 | + |
| 20 | + % Edge vectors |
| 21 | + d1 = v2 - v1; |
| 22 | + d2 = v3 - v1; |
| 23 | + |
| 24 | + % Cross product (2 * triangle area vector) |
| 25 | + n = cross(d1, d2, 2); |
| 26 | + n_len_sq = sum(n.^2, 2); |
| 27 | + |
| 28 | + if nargout > 1 |
| 29 | + % Circumcenter (needed for radius anyway if requested) |
| 30 | + alpha = sum(d2.^2, 2) .* dot(d1, d1 - d2, 2) ./ (2 * n_len_sq); |
| 31 | + beta = sum(d1.^2, 2) .* dot(d2, d2 - d1, 2) ./ (2 * n_len_sq); |
| 32 | + cc = v1 + alpha .* d1 + beta .* d2; |
| 33 | + |
| 34 | + % Circumradius from center |
| 35 | + r = sqrt(sum((v1 - cc).^2, 2)); |
| 36 | + else |
| 37 | + % Circumradius without computing center |
| 38 | + a = sqrt(sum((v2 - v3).^2, 2)); |
| 39 | + b = sqrt(sum(d2.^2, 2)); |
| 40 | + c = sqrt(sum(d1.^2, 2)); |
| 41 | + area = sqrt(n_len_sq) / 2; |
| 42 | + r = (a .* b .* c) ./ (4 * area); |
| 43 | + end |
| 44 | + |
| 45 | +else % Tetrahedral mesh |
| 46 | + % Get tet vertices |
| 47 | + v1 = p(t(:, 1), :); |
| 48 | + v2 = p(t(:, 2), :); |
| 49 | + v3 = p(t(:, 3), :); |
| 50 | + v4 = p(t(:, 4), :); |
| 51 | + |
| 52 | + % Edge vectors from v1 |
| 53 | + a = v2 - v1; |
| 54 | + b = v3 - v1; |
| 55 | + c = v4 - v1; |
| 56 | + |
| 57 | + if nargout > 1 |
| 58 | + % Circumcenter using Cramer's rule |
| 59 | + d1 = sum(c .* (v1 + v4) * 0.5, 2); |
| 60 | + d2 = sum(a .* (v1 + v2) * 0.5, 2); |
| 61 | + d3 = sum(b .* (v1 + v3) * 0.5, 2); |
| 62 | + |
| 63 | + det23 = a(:, 2) .* b(:, 3) - a(:, 3) .* b(:, 2); |
| 64 | + det13 = a(:, 3) .* b(:, 1) - a(:, 1) .* b(:, 3); |
| 65 | + det12 = a(:, 1) .* b(:, 2) - a(:, 2) .* b(:, 1); |
| 66 | + |
| 67 | + Det = c(:, 1) .* det23 + c(:, 2) .* det13 + c(:, 3) .* det12; |
| 68 | + |
| 69 | + detx = d1 .* det23 + c(:, 2) .* (-(d2 .* b(:, 3)) + (a(:, 3) .* d3)) + ... |
| 70 | + c(:, 3) .* ((d2 .* b(:, 2)) - (a(:, 2) .* d3)); |
| 71 | + dety = c(:, 1) .* ((d2 .* b(:, 3)) - (a(:, 3) .* d3)) + d1 .* det13 + ... |
| 72 | + c(:, 3) .* ((d3 .* a(:, 1)) - (b(:, 1) .* d2)); |
| 73 | + detz = c(:, 1) .* ((a(:, 2) .* d3) - (d2 .* b(:, 2))) + ... |
| 74 | + c(:, 2) .* (d2 .* b(:, 1) - a(:, 1) .* d3) + d1 .* det12; |
| 75 | + |
| 76 | + cc = [detx ./ Det, dety ./ Det, detz ./ Det]; |
| 77 | + |
| 78 | + % Circumradius from center |
| 79 | + r = sqrt(sum((v2 - cc).^2, 2)); |
| 80 | + else |
| 81 | + % Circumradius without computing center |
| 82 | + V = abs(dot(a, cross(b, c, 2), 2)) / 6; |
| 83 | + A = [sqrt(sum(cross(b, c, 2).^2, 2)), ... |
| 84 | + sqrt(sum(cross(c, a, 2).^2, 2)), ... |
| 85 | + sqrt(sum(cross(a, b, 2).^2, 2)), ... |
| 86 | + sqrt(sum(cross(v3 - v2, v4 - v2, 2).^2, 2))] / 2; |
| 87 | + r = sqrt(sum(A.^2, 2)) ./ (4 * V); |
| 88 | + end |
| 89 | +end |
0 commit comments