如何根据 python 中的某些平面拆分 3D 中的某些点

How to split some points in 3D based on some planes in python

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

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

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

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

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

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., 20., 60.], [20., 30., 65.]]), np.array([[55., 30., 80.]]), np.array([[80., 10., 60.]]),\
  np.array([[20., 10., 55.]]), np.array([[60., 30., 70.]]), np.array([[70., 15., 20.]])]]

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

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

一些观察:

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

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

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

  • 与其在 for 乘积前减去 corners[0],还不如从结果中减去 for 与 p(即 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., 30., 80.]]),
  np.array([[80., 10., 60.]]),
  np.array([[20., 10., 55.]]),
  np.array([[60., 30., 70.]]),
  np.array([[70., 15., 20.]])]]

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

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

https://ideone.com/oo5GFg 有一个将所有内容放在一起的工作示例。