Skip to content

Commit 7763356

Browse files
committed
Merge PR #279: Fix intersection of three planes
2 parents 6f641a0 + 4ab65ff commit 7763356

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

‎spatialmath/geom3d.py‎

100755100644
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def intersection(pi1: Plane3, pi2: Plane3, pi3: Plane3) -> R3:
145145
"""
146146
A = np.vstack([pi1.n, pi2.n, pi3.n])
147147
b = np.array([pi1.d, pi2.d, pi3.d])
148-
return np.linalg.det(A) @ b
148+
return np.linalg.solve(A, -b)
149149

150150
@property
151151
def n(self) -> R3:

‎tests/test_geom3d.py‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,5 +442,33 @@ def test_methods(self):
442442
# py.intersect_plane(plane)
443443

444444

445+
@pytest.mark.parametrize("point", [[0, 0, 0], [1, 2, 3], [-1.5, 2, 3.25]])
446+
@pytest.mark.parametrize(
447+
"normals", [np.eye(3), np.array([[1, 2, 0], [0, 1, 3], [2, 0, 1]])]
448+
)
449+
@pytest.mark.parametrize("scales", [[1, 1, 1], [-2, 0.5, 3]])
450+
def test_three_plane_intersection(point, normals, scales):
451+
normals = normals * np.array(scales)[:, None]
452+
planes = [Plane3.PointNormal(point, normal) for normal in normals]
453+
intersection = Plane3.intersection(*planes)
454+
455+
assert intersection.shape == (3,)
456+
nt.assert_allclose(intersection, point, atol=1e-12)
457+
# Each plane is defined by n @ x + d = 0, regardless of coefficient scale.
458+
nt.assert_allclose(
459+
normals @ intersection + np.array([plane.d for plane in planes]),
460+
0,
461+
atol=1e-12,
462+
)
463+
nt.assert_allclose(Plane3.intersection(*reversed(planes)), point, atol=1e-12)
464+
465+
466+
@pytest.mark.parametrize("offset", [0, 1])
467+
def test_three_plane_intersection_singular(offset):
468+
planes = [Plane3([1, 0, 0, 0]), Plane3([1, 0, 0, offset]), Plane3([0, 1, 0, 0])]
469+
with pytest.raises(np.linalg.LinAlgError):
470+
Plane3.intersection(*planes)
471+
472+
445473
if __name__ == "__main__":
446474
unittest.main()

0 commit comments

Comments
 (0)