如何找到关于某个坐标的表面最近点?

问题描述

我在 3d 空间(x、y 和 z)中有一堆点,并且想找到点之间存在的最接近表面的点。我阅读了 this solution,但无法解决我的问题。我的表面是由四个点创建的:

PRECISION = 1e-8    # Arbitrary zero for real-world purposes
def plane_from_points(points):
    centroid = np.mean(points,axis=0)
    _,eigenvalues,eigenvectors = np.linalg.svd(points - centroid)
    if eigenvalues[1] < PRECISION:
        raise ValueError("Points are aligned,can't define a plane")
    normal = eigenvectors[2]
    d = -np.dot(centroid,normal)
    plane = np.append(normal,d)
    thickness = eigenvalues[2]
    return plane,thickness

我的点中有一个倾斜的(由我的无花果中的黑点显示)和一个正常的(由黄点显示)表面。曲面的角是:

surf_corners=[np.array([[1.,1.,1.],[1.5,2.,[3.,3.],[3.5,3.]]),\
              np.array([[5.,4.],[5.,[7.,2.],2.]])]

一个阵列是倾斜的,第二个阵列是正常的。这些是我想找到表面的壁橱点的点:

surrounding_points=[np.array([[2.,3.2],\
                    np.array([[6.,2.5],[6.,3.5],3.5]])]

surrounding_points 的第一个数组(由蓝色方块显示)的投影应该在由 surf_corners 的第一个数组创建的表面上找到,第二个数组(由红色方块显示)也与第二个表面。我的表面应该只在它的四个角之间,而不是无穷大。我的意思是计算点的 y 值不应小于或大于角点。例如,我更喜欢保持 ysurrounding_points 值。我的意思是第一点,我想要创建的表面的壁橱点,它的 y 值为 1。为简单起见,我只复制了它们的 y 值等于我平面的 brders 的数据,实际上我可能在平面的 brders 之间还有其他具有 y 值的点,但我仍然想找到投影具有固定的 y 值。我尝试了以下方法来这样做,但它只是给了我一个表面的水平投影,我无法处理两个表面(当 surf_cornerssurrounding_points 是 numpy 数组而不是 numpy 数组列表时) :

pls=[]
for i in surf_corners:
    i=i.tolist()
    pl,thickness= plane_from_points(i)
    pls.append(pl)
point_on_surf=[]
n_iter=1
for i in range (n_iter):
    a,b,c,d = pls[i][0],pls[i][1],pls[i][2],pls[i][3]
    def fun(row):
        row[0] = -(d + b * row[1] + c * row[2]) / a # calculates new x
        return row[0],row[1],row[2] # new x and old y and z
    to_be_projected=[copy.copy(surrounding_points[i])]
    new_points = np.asarray(list(map(fun,[x for point in to_be_projected for x in point])))
    point_on_surf.append(new_points)

为了更清楚,我上传了一张图。绿色箭头显示我想要的投影点(具有相同 y 值的最近点)。在此之前,我非常感谢任何帮助。

enter image description here

解决方法

我了解您需要解决以下问题:

  1. 给定形成平面四边形的四个 3D 点,确定这些点所在的平面。
  2. 将任意 3D 点投影到平面上。
  3. 检查投影点是否位于四边形内。

问题1.确定平面

我了解您正在使用 this answer 中的代码,因此我不会再发表任何评论。

问题 2. 投影一个点

您可以使用

计算投影点
projected_point = p - np.dot(p - p0,u) * u

哪里

  • p 是项目点
  • p0 是平面上的一个点(定义四边形的点之一,它们的质心...)
  • u 是平面的单位法向量

编辑:


只要平面计算方法提供平面系数 (a,b,c,d) 其中 (a,c) 是平面的法向量,也是单位向量,就可以使用:

u = plane[:3]                      # Plane's normal unit vector
d = plane[3]                       # Signed distance plane - origin of coordinates
distance = np.dot(u,point) + d    # Signed distance point - plane
projected_point = point - distance * u

问题 3. 指向四边形内

我建议使用 winding number 方法。而且,如果您知道四边形是凸的,则可以利用同一链接中描述的优化。