如何根据python中的一些平面在3D中分割一些点

问题描述

在 3D 空间中,我有一些点(xyz)并希望通过重建一些现有平面来分割它们。这些是我的简化点:

points=[[np.array([[20.,20.,60.],[20.,30.,65.],[55.,80.],[80.,10.,60.]]),\
         np.array([[20.,55.],[60.,70.],[70.,15.,20.]])]]

大列表有一个包含两个数组的子列表。我现实 points 有更多的子列表,每个子列表也可能有几个数组。然后,在这个简化的例子中,我在点之间有两个平面。我有两个表面的四个角:

four_corners= [[np.array([[50.,5.,5.],[50.,45.,95.],95.]]),np.array([[30.,[30.,5.]])]]

four_corners一个子列表,这个子列表也有两个数组,即两个表面。然后,points 的第一个子列表的每个数组应该被分成三个部分,因为有两个表面通过它们。如果有一架飞机,我将为每个阵列进行两次拆分。我想根据表面分割我的观点。我试图修改 this solution 但我无法达到我想要的。我尝试了以下代码,但没有成功:

splitted_arr=[]
for m in points:
    for surfaces in four_corners:
        for i,j in zip (m,surfaces):
            j=np.array(j)
            corners = [j[0],j[1],j[2]]
            v1 = np.subtract(corners[1],corners[0])
            v1 = v1 / np.linalg.norm(v1)
            v2 = np.subtract(corners[-1],corners[0])
            v2 = v2 / np.linalg.norm(v2)
            orth = np.cross(v1,v2)
            for p in i:
                p_moved = np.subtract(p,corners[0])
                d = np.dot(orth,p_moved)
                if d < 0:
                    splitted_arr.append (p)
                else:
                    splitted_arr.append (p)

我想得到:

[[np.array([[20.,65.]]),np.array([[55.,80.]]),np.array([[80.,\
  np.array([[20.,55.]]),np.array([[60.,70.]]),np.array([[70.,20.]])]]

关键规则是我想始终使用现有平面分割我的点。在此之前,我非常感谢任何帮助和贡献。

解决方法

您的方法的一般原则看起来很合理。您在案例区分的每个分支中调用 splitted_arr.append (p) 的事实使这几乎没有实际意义。所以说这是你的主要问题。

一些观察:

  • 请注意,您从未使用过 j[3]。因此,您可以通过仅使用三个而不是四个点来定义平面来简化事情,这样做可以消除 for 点不位于单个平面上的不一致的可能性。

  • 您可能希望针对点的循环外的每个表面计算 ortho,以减少重复计算并提高性能。

  • 您的应用程序不需要将 v1v2 中的每一个除以其长度的标准化步骤,因此您可以省略它。这将影响结果的大小,但不会影响符号。

  • 与其在for积之前减去corners[0],还不如从for积的结果中减去那个和p的for积(即np.dot(orth,corners[0])) .这用标量减法代替了向量减法。或者,更好的是,不要减去该数字并与零进行比较,而是立即与该数字进行比较。同样,角落的点积是您可以在所有点的循环外计算的东西。所有这些都将有助于提高性能而不改变结果(除了潜在的舍入差异)。

预先计算每个平面的 ortho 向量和角点积在概念上与将其转换为标准形式相同,即为平面上的每个点找到 a,b,c,d 使得 a*x+b*y+c*z=d。对于不是在 numpy 库上构建的读者来说,这种表述可能特别有吸引力。

在你的问题中你写道(我重新格式化)你想要

[[np.array([[20.,20.,60.],[20.,30.,65.]]),np.array([[55.,80.]]),np.array([[80.,10.,60.]]),np.array([[20.,55.]]),np.array([[60.,70.]]),np.array([[70.,15.,20.]])]]

为什么?为什么前两个点在一个组中,而所有其他点都是分开的?你真的想再次将多个点组合成一个二维数组吗?

在下面的评论中,您写道,表达相对于多个平面的关系是使这变得困难的部分原因。本质上,给定一个点和一个(定向)平面列表,您可以决定该点是在每个平面的正侧还是负侧(忽略完全在平面上的情况,出于四舍五入的原因应该无论如何都不要依赖)。因此,对于每个点和平面,您都会获得一点相关信息,对于此类平面的列表,您将获得这些比较结果的列表。您可以将它们用作键来对没有被任何平面彼此分开的点进行分组。选择每个平面的哪一边是正的,哪一边是负的并不重要,只要它始终如一地完成,即每个 ortho 只计算一次或至少总是以相同的方式计算。

https://ideone.com/oo5GFg 有一个工作示例,可以将它们组合在一起。