numpy 求由四个3d点组成的平面的矢量

falq053o  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(101)

我有四个3D点(图像上的蓝色球体)以固定的二次方式排列在平面上。我想找到从平面中心向上的矢量。我知道我必须首先计算出3D点来找到平面的中心,但是如何计算出那个矢量呢?

x    y    z
30, 210, -176
0, 210, -176
30, 180, -176
0, 180, -176

字符串


的数据

kq0g1dla

kq0g1dla1#

注意,你只需要 * 三个 * 点来定义一个平面。四个点可能定义不了一个平面,但是如果你能保证你的输入确实如此,那就太酷了。
由于向量垂直于平面,你只需要计算连接一对点的向量与连接另一对点的向量的叉积。为了确保这些向量的叉积不为零,我们选择我们的对,使得其中一个点是两对的公共点。由于三个点足以定义一个平面,这应该可以正常工作。在下面的代码中,我使用连接点0到点1和点0到点2的向量:

pts = np.array([[30, 210, -176],
                [0, 210, -176],
                [30, 180, -176],
                [0, 180, -176]])

vec1 = pts[0, :] - pts[1, :]
vec2 = pts[0, :] - pts[2, :]

plane_normal = np.cross(vec1, vec2) # array([0, 0, 900])

字符串
如果你想要单位向量,你可以用它的L2范数来归一化plane_normal

plane_normal /= np.linalg.norm(plane_normal) # array([0, 0, 1])


我们可以在随机点上进行测试:

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}")

相关问题