使用python在3D中通过点进行平面拟合

时间:2018-12-10 08:03:23

标签: python-3.x matplotlib geometry

我在3D空间中有点。

       X        Y       Z
0   0.61853 0.52390 0.26304
1   0.61843 0.52415 0.26297 
2   0.62292 0.52552 0.26108 
3   0.62681 0.51726 0.25622 
4   0.62772 0.51610 0.25903 

我已经定义了一个通过这些点的平面,这些点应该在垂直方向上划分这些点,但并不是在垂直或水平方向上划分它们。我在绘制平面和点时相距遥远。

def plane_equation(x1, y1, z1, x2, y2, z2, x3, y3, z3):
    a1 = x2 - x1 
    b1 = y2 - y1 
    c1 = z2 - z1 
    a2 = x3 - x1 
    b2 = y3 - y1 
    c2 = z3 - z1 
    a = b1 * c2 - b2 * c1 
    b = a2 * c1 - a1 * c2 
    c = a1 * b2 - b1 * a2 
    d = (- a * x1 - b * y1 - c * z1) 
    return a, b, c, d

# Finding the equation of the plane
a, b, c, d = plane_equation(x0, y0, z0, x1, y1, z1, x2, y2, z2)
print("equation of plane is ", a, "x +", b, "y +", c, "z +", d, "= 0.")

x = np.arange(0, 1, 0.1)
y = np.arange(0, 1, 0.1)

X,Y = np.meshgrid(x,y)
Z = a*X + b*Y + d

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.scatter(df.x, df.y, df.z, color = 'c', marker = 'o', alpha = 0.5)
surf = ax.plot_surface(X, Y, Z)

equation of plane is  -0.0002496952000000007 x + 0.00036812320000000016 y + 0.0007697304000000002 z + -0.00024088567529317268 = 0.

我需要平面穿过这些点,并且应该在垂直方向上。蓝色平面应穿过青色点,且平面应垂直。

1 个答案:

答案 0 :(得分:1)

这里有些事情可能会出错:

  1. 值太小

    您的法线未规范化,并且其坐标的幅度很小(0.000???),因此您的图可能会将所有值都视为零(因为图像上的图是Z=0的平面,与您提供的值无关。

    根据您的反馈in chat我的这个假设是正确的,因此要解决此问题,只需将您的法线归一即可:

    n(nx,ny,nz) /= sqrt(nx*nx + ny*ny +nz*nz) 
    

    并使用以下新值计算d

    d = nx*x0 + ny*y0 + nz*z0
    

    其中(x0,y0,z0)是所选点中的任意一个。

  2. 错误选择的点

    3个选定的点应该彼此不太靠近,并且不能位于一行上。如果这样做,则计算的法线无效。另外,如果您选择包含大噪声的点,则精度会因此降低...

    要改善此效果,请选择3个点,随机计算法线。计算n这样的法线并将其平均。 n越高,准确性越好。

  3. 适合

    要进一步提高准确性,您可以尝试拟合法线和d。只需使用#1 #2 中的法线,并使其坐标和d位于附近范围内,以最小化所有点到平面的平均或最大距离。但是,这是O(n.log^4(m)),其中n是已使用的点数,m与每个参数的拟合范围有关,但是可以提供最佳的精度。

    您可以使用二进制搜索或Approximation search或您的环境可以使用的任何优化程序