Skip to content

Commit ffb136a

Browse files
committed
Add test for new circumcenter()
1 parent 305ffbe commit ffb136a

1 file changed

Lines changed: 113 additions & 0 deletions

File tree

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import collections
2+
3+
import numpy as np
4+
5+
from mpas_tools.mesh.creation.util import circumcenter
6+
7+
point = collections.namedtuple('Point', ['x', 'y', 'z'])
8+
9+
10+
def test_circumcenter_planar():
11+
# Use provided cell coordinates and vertex as expected output
12+
x1, y1, z1 = 0.0, 17320.50807569, 0.0
13+
x2, y2, z2 = 10000.0, 17320.50807569, 0.0
14+
x3, y3, z3 = 5000.0, 25980.76211353, 0.0
15+
expected = (5000.0, 20207.25942164, 0.0)
16+
17+
xv, yv, zv = circumcenter(False, x1, y1, z1, x2, y2, z2, x3, y3, z3)
18+
assert np.allclose([xv, yv, zv], expected, atol=1e-8), (
19+
f'Planar circumcenter failed: got {[xv, yv, zv]}, expected {expected}'
20+
)
21+
22+
xv_old, yv_old, zv_old = _old_circumcenter(
23+
False, x1, y1, z1, x2, y2, z2, x3, y3, z3
24+
)
25+
# Print both sets and their difference
26+
print('Planar circumcenter:')
27+
print(' circumcenter: ', (xv, yv, zv))
28+
print(' _old_circumcenter: ', (xv_old, yv_old, zv_old))
29+
print(' difference: ', (xv - xv_old, yv - yv_old, zv - zv_old))
30+
# Check for exact equality
31+
assert np.array_equal([xv, yv, zv], [xv_old, yv_old, zv_old]), (
32+
f'circumcenter and _old_circumcenter results differ: '
33+
f'({xv}, {yv}, {zv}) != ({xv_old}, {yv_old}, {zv_old})'
34+
)
35+
36+
37+
def test_circumcenter_sphere():
38+
# Use provided cell coordinates and vertex as expected output
39+
x1, y1, z1 = -3590.95704026, -684.52527287, -6371218.95125671
40+
x2, y2, z2 = -9926.94769501, 18734.26792821, -6371184.72274307
41+
x3, y3, z3 = 12921.92507847, 11340.69768405, -6371196.8028643
42+
expected = (296.83807146, 11327.05862805, -6371209.92418473)
43+
44+
xv, yv, zv = circumcenter(True, x1, y1, z1, x2, y2, z2, x3, y3, z3)
45+
assert np.allclose([xv, yv, zv], expected, atol=1e-8), (
46+
f'Spherical circumcenter failed: got {[xv, yv, zv]}, expected '
47+
f'{expected}'
48+
)
49+
50+
xv_old, yv_old, zv_old = _old_circumcenter(
51+
True, x1, y1, z1, x2, y2, z2, x3, y3, z3
52+
)
53+
# Print both sets and their difference
54+
print('Spherical circumcenter:')
55+
print(' circumcenter: ', (xv, yv, zv))
56+
print(' _old_circumcenter: ', (xv_old, yv_old, zv_old))
57+
print(' difference: ', (xv - xv_old, yv - yv_old, zv - zv_old))
58+
# Check for exact equality
59+
assert np.array_equal([xv, yv, zv], [xv_old, yv_old, zv_old]), (
60+
f'circumcenter and _old_circumcenter results differ: '
61+
f'({xv}, {yv}, {zv}) != ({xv_old}, {yv_old}, {zv_old})'
62+
)
63+
64+
65+
def _old_circumcenter(on_sphere, x1, y1, z1, x2, y2, z2, x3, y3, z3):
66+
"""
67+
Compute the circumcenter of the triangle (possibly on a sphere)
68+
with the three given vertices in Cartesian coordinates.
69+
70+
Returns
71+
-------
72+
center : point
73+
The circumcenter of the triangle with x, y and z attributes
74+
75+
"""
76+
p1 = point(x1, y1, z1)
77+
p2 = point(x2, y2, z2)
78+
p3 = point(x3, y3, z3)
79+
if on_sphere:
80+
a = (p2.x - p3.x) ** 2 + (p2.y - p3.y) ** 2 + (p2.z - p3.z) ** 2
81+
b = (p3.x - p1.x) ** 2 + (p3.y - p1.y) ** 2 + (p3.z - p1.z) ** 2
82+
c = (p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2 + (p1.z - p2.z) ** 2
83+
84+
pbc = a * (-a + b + c)
85+
apc = b * (a - b + c)
86+
abp = c * (a + b - c)
87+
88+
xv = (pbc * p1.x + apc * p2.x + abp * p3.x) / (pbc + apc + abp)
89+
yv = (pbc * p1.y + apc * p2.y + abp * p3.y) / (pbc + apc + abp)
90+
zv = (pbc * p1.z + apc * p2.z + abp * p3.z) / (pbc + apc + abp)
91+
else:
92+
d = 2 * (
93+
p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)
94+
)
95+
96+
xv = (
97+
(p1.x**2 + p1.y**2) * (p2.y - p3.y)
98+
+ (p2.x**2 + p2.y**2) * (p3.y - p1.y)
99+
+ (p3.x**2 + p3.y**2) * (p1.y - p2.y)
100+
) / d
101+
yv = (
102+
(p1.x**2 + p1.y**2) * (p3.x - p2.x)
103+
+ (p2.x**2 + p2.y**2) * (p1.x - p3.x)
104+
+ (p3.x**2 + p3.y**2) * (p2.x - p1.x)
105+
) / d
106+
zv = 0.0
107+
108+
# Optional method to use barycenter instead.
109+
# xv = p1.x + p2.x + p3.x
110+
# xv = xv / 3.0
111+
# yv = p1.y + p2.y + p3.y
112+
# yv = yv / 3.0
113+
return point(xv, yv, zv)

0 commit comments

Comments
 (0)