Skip to content

Commit 1ed72ff

Browse files
committed
add plan tests
1 parent d45e96e commit 1ed72ff

File tree

4 files changed

+126
-3
lines changed

4 files changed

+126
-3
lines changed

core_geometry/plane.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ def from_rays(cls, ray1, ray2, origin):
3636

3737
def signed_distance_to(self, point):
3838
"""Compute signed distance from a point to the plane."""
39-
point = np.array(point)
39+
point = np.array(point) # In case point is a list or tuple
4040
return np.dot(self.normal, point) + self.offset
4141

4242
def project_point(self, point):
4343
"""Project a point orthogonally onto the plane."""
44-
point = np.array(point)
44+
point = np.array(point) # In case point is a list or tuple
4545
d = self.signed_distance_to(point)
4646
return point - d * self.normal
4747

tests/__init__.py

Whitespace-only changes.

tests/dummy_test_2.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# tests/dummy_test_2.py
22

33
def test_always_fails():
4-
assert 1 + 1 == 3, "This test is designed to fail."
4+
# assert 1 + 1 == 3, "This test is designed to fail."
5+
assert 1 + 1 == 2, "This test is designed to succeed."
56

67
if __name__ == "__main__":
78
test_always_fails()

tests/test_plane.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
from core_geometry.plane import Plane
2+
import numpy as np
3+
4+
def test_plane_from_points_horizontal():
5+
"""
6+
Create a horizontal plane using three points and verify its normal and offset.
7+
"""
8+
p1 = [0, 0, 0]
9+
p2 = [1, 0, 0]
10+
p3 = [0, 0, 1]
11+
plane = Plane.from_points(p1, p2, p3)
12+
assert np.allclose(np.abs(plane.normal), [0, 1, 0]) or np.allclose(np.abs(plane.normal), [0, -1, 0])
13+
assert np.isclose(plane.offset, 0)
14+
15+
def test_plane_from_points_inclined():
16+
"""
17+
Create an inclined plane using three points and verify that the signed distance to each point is zero.
18+
"""
19+
p1 = [0, 0, 0]
20+
p2 = [1, 1, 0]
21+
p3 = [0, 1, 1]
22+
plane = Plane.from_points(p1, p2, p3)
23+
for p in (p1, p2, p3):
24+
assert np.isclose(plane.signed_distance_to(p), 0)
25+
26+
def test_plane_from_collinear_points_raises():
27+
"""
28+
Attempt to create a plane from three collinear points and expect a ValueError.
29+
"""
30+
p1 = [0, 0, 0]
31+
p2 = [1, 0, 0]
32+
p3 = [2, 0, 0]
33+
try:
34+
Plane.from_points(p1, p2, p3)
35+
assert False, "Expected ValueError"
36+
except ValueError:
37+
pass
38+
39+
def test_plane_signed_distance_positive():
40+
"""
41+
Test signed distance to a horizontal plane with points above and below it.
42+
"""
43+
plane = Plane([0, 1, 0], [0, 0, 0])
44+
assert np.isclose(plane.signed_distance_to([0, 5, 0]), 5)
45+
assert np.isclose(plane.signed_distance_to([0, -3, 0]), -3)
46+
47+
def test_plane_project_points():
48+
"""
49+
Project a point onto a horizontal plane and verify the result.
50+
"""
51+
plane = Plane([0, 1, 0], [0, 0, 0])
52+
points = [[1, 5, 1], [1, -3, 1], [1, 0, 1]]
53+
for point in points:
54+
projected = plane.project_point(point)
55+
assert np.isclose(projected[1], 0)
56+
57+
def test_plane_from_rays_basic():
58+
"""
59+
Create a plane from two rays and verify that the normal is orthogonal to both rays.
60+
"""
61+
ray1 = np.array([1, 0, 0], dtype=float)
62+
ray2 = np.array([0, 0, 1], dtype=float)
63+
origin = [0, 0, 0]
64+
plane = Plane.from_rays(ray1, ray2, origin)
65+
expected_normal = np.cross(ray1, ray2)
66+
expected_normal = expected_normal / np.linalg.norm(expected_normal)
67+
assert np.allclose(np.abs(plane.normal), expected_normal) or np.allclose(np.abs(plane.normal), -expected_normal)
68+
69+
def test_plane_from_collinear_rays_raises():
70+
"""
71+
Attempt to create a plane from two collinear rays and expect a ValueError.
72+
"""
73+
ray1 = [1, 0, 0]
74+
ray2 = [2, 0, 0]
75+
origin = [0, 0, 0]
76+
try:
77+
Plane.from_rays(ray1, ray2, origin)
78+
assert False, "Expected ValueError"
79+
except ValueError:
80+
pass
81+
82+
def test_plane_normalization_enforced():
83+
# plane = Plane([0, 10, 0], [0, 0, 0])
84+
# assert np.allclose(plane.normal, [0, 1, 0])
85+
# assert np.isclose(plane.offset, 0)
86+
planes = [Plane([0, 10, -7], [0, 1, 0]),
87+
Plane([5, -10, 0], [2, 0, 0]),
88+
Plane([0, 1, 10], [0, 0, -3]),
89+
Plane([2, 0, -10], [1, 0, 5])]
90+
for plane in planes:
91+
# assert np.linalg.norm(plane.normal) == 1, f"Plane normal not normalized: {plane.normal}"
92+
assert np.isclose(np.linalg.norm(plane.normal), 1), f"Plane normal not normalized: {plane.normal}"
93+
94+
def test_plane_equation():
95+
p1 = [3, 4, 5]
96+
p2 = [1, 0, 0]
97+
p3 = [8, -2, 1]
98+
plane = Plane.from_points(p1, p2, p3)
99+
A, B, C = plane.normal
100+
D = plane.offset
101+
# Equation is A*x + B*y + C*z + D = 0
102+
# Launch random rays and verify that the intersection point satisfies the plane equation
103+
# ray_positions, ray_dirs = [np.array(-5, -100, 0)], [np.array([1, 0, -15])], [np.array([0, 1, 0]), np.array([0, 0, 1])]
104+
ray_positions = np.array([[0, 0, 10], [0, 10, 10], [10, 0, 10], [5, 5, -10], [-10, -10, 10]])
105+
ray_dirs = np.array([[0, 0, -1], [0, -1, -1], [-1, 0, -1], [-0.5, -0.5, 2], [1, 1, -1]])
106+
intersections = []
107+
for pos, dir in zip(ray_positions, ray_dirs):
108+
intersection = plane.project_point(pos + dir)
109+
intersections.append(intersection)
110+
assert np.isclose(A * intersection[0] + B * intersection[1] + C * intersection[2] + D, 0)
111+
112+
if __name__ == "__main__":
113+
test_plane_from_points_horizontal()
114+
test_plane_from_points_inclined()
115+
test_plane_from_collinear_points_raises()
116+
test_plane_signed_distance_positive()
117+
test_plane_project_points()
118+
test_plane_from_rays_basic()
119+
test_plane_from_collinear_rays_raises()
120+
test_plane_normalization_enforced()
121+
test_plane_equation()
122+
print("All tests passed!")

0 commit comments

Comments
 (0)