假设我有一个 n
3D点列表存储在一个形状为 (3, n)
的Numpy数组中 . 我想在该列表中找到所有4个点的集合,使得4个点是共面的 . 我怎样才能做到这一点?
例如,给定一个 points
数组,其中包含在3D空间中围绕任意角度旋转的立方体的8个顶点(无特定顺序):
points = np.array([[ 0.8660254 , 0.8660254 , 0. , 0.3660254 , -0.5 , 0.3660254 , 0. , -0.5 ],
[ 0.35355339, -0.35355339, 0.70710678, -0.25881905, 0.09473435, -0.96592583, 0. , -0.61237244],
[ 1.06066017, 0.35355339, 0.70710678, 1.67303261, 1.31947922, 0.96592583, 0. , 0.61237244]])
如何找到位于立方体每个面角落的6组4个顶点?具体来说,我正在寻找一个完全矢量化的基于Numpy / Scipy的解决方案 .
Edit :正如ShlomiF所指出的,实际上有12个立方体顶点的共面集,包括沿着立方体的面对角线位于平面上的顶点 .
这是我用来生成 points
的代码:
import numpy as np
import scipy.linalg as spl
def rot(axis, theta):
return spl.expm(np.cross(np.eye(len(axis)), axis/spl.norm(axis)*theta))
rot3 = rot((1,0,0), np.pi/4) @ rot((0,1,0), np.pi/3) @ rot((0,0,1), np.pi/2)
points = np.array([[1, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 1],
[1, 1, 0, 1, 0, 1, 0, 0]])
points = rot3 @ points
2 回答
以下可能不是一个非常快速的解决方案,但它的工作原理和数学/几何意义 .
但首先 - 请注意,由于"diagonal"飞机穿过你的立方体,你的例子有4个共面点的 12 子集,而不是8个 . 这可以正式化,但应该清楚(如果不是通过评论,请告诉我) .
在我们的方式中,最简单的方法是生成大小为4的所有子集(没有用于重新排序的重复),然后检查由4个点定义的体积是否为0;即这4个点中的任何3个定义包含第4个的平面 . (此方法在许多堆栈交换问题中进行了解释,并且也显示在_47508中) .
实现这一点可以简单地完成如下:
你得到了所有12个4组共面点 .
使用以下简单代码获得的点的简单可视化(从最后一个片段继续,带有额外的导入):
这产生了以下可视化(再次,对于此特定示例):
希望有所帮助 .
祝好运!
有四个点的70个子集,您需要计算它们形成的四面体的体积 . 如果你的形状足够接近立方体,那么共面的集合将是具有最小体积的十二个 .
对于任意体积,您还可以比较通过将体积除以四个中最大面部的面积而获得的高度 . 这将需要
体积计算和面积计算的四倍 .
一个详尽的方法将是可怕的(O(n ^ 4)!) . 并且矢量化将需要在几何计算之前准备顶点的所有组合 .