def plane_norm(pts):
vec1 = pts[0, :] - pts[1, :]
vec2 = pts[0, :] - pts[2, :]
plane_normal = np.cross(vec1, vec2)
return plane_normal / np.linalg.norm(plane_normal)
np.random.seed(100) # For repeatable results
p = np.random.random((3, 3)) * 5 # three points because they're guaranteed to make a plane
m = p.mean(axis=0) # Mid point
n = plane_norm(p) # Normal
from matplotlib import pyplot as plt
fig, ax = plt.subplots(subplot_kw={'projection': '3d'})
ax.plot_trisurf(p[:, 0], p[:, 1], p[:, 2], alpha=0.5)
ax.plot3D(*m, 'or')
ax.quiver(*m, *n)
ax.set_aspect('equal')
型 这导致了这个图:
在旋转视图以看到正面的平面后,很明显我们有正确的矢量:
如果你想确保你的四个点在同一个平面上,你可以计算前三个点的法线,并确保它接近后三个点的法线:
n1 = plane_norm(pts[:3, :])
n2 = plane_norm(pts[1:, :])
if not (np.allclose(n1, n2) or np.allclose(n1, -n2)):
print("ERROR: the four points are not coplanar")
else:
print(f"The normal vector is {n1}")
1条答案
按热度按时间kq0g1dla1#
注意,你只需要 * 三个 * 点来定义一个平面。四个点可能定义不了一个平面,但是如果你能保证你的输入确实如此,那就太酷了。
由于向量垂直于平面,你只需要计算连接一对点的向量与连接另一对点的向量的叉积。为了确保这些向量的叉积不为零,我们选择我们的对,使得其中一个点是两对的公共点。由于三个点足以定义一个平面,这应该可以正常工作。在下面的代码中,我使用连接点0到点1和点0到点2的向量:
字符串
如果你想要单位向量,你可以用它的L2范数来归一化
plane_normal
:型
我们可以在随机点上进行测试:
型
这导致了这个图:
在旋转视图以看到正面的平面后,很明显我们有正确的矢量:
如果你想确保你的四个点在同一个平面上,你可以计算前三个点的法线,并确保它接近后三个点的法线:
型