Matlab delaunayn与Scipy Delaunay的区别

zep*_*hyr 5 python matlab delaunay scipy qhull

我正在尝试使用scipy.spatial.Delaunay函数复制由Python中的Matlab delaunayn函数执行的N维Delaunay三角剖分.然而,虽然Matlab函数给了我想要和期望的结果,但是scipy给了我不同的东西.考虑到两者都是QHull库的包装器,我发现这很奇怪.我假设Matlab在其调用中隐式设置了不同的参数.我试图在两者之间复制的情况可以在Matlab的文档中找到.

设置是在中心有一个点,如下所示.我提供的蓝线有助于形象化,但它们没有任何目的或意义.

一个点在中心的立方体

我期望的三角测量结果是12个单纯形式(在Matlab示例中列出),如下所示.

Matlab的三角测量

然而,这个python等效产生"额外"的单纯形.

x = np.array([[-1,-1,-1],[-1,-1,1],[-1,1,-1],[1,-1,-1],[1,1,1],[1,1,-1],[1,-1,1],[-1,1,1],[0,0,0]])
simp = scipy.spatial.Delaunay(x).simplices
Run Code Online (Sandbox Code Playgroud)

返回的变量simp应该是一个M×N数组,其中M是找到的单纯数(对于我的情况应该是12),N是单数中的点数.在这种情况下,每个单形都应该是四面体,意味着N是4.

我发现的是,M实际上是18,额外的6个单纯形不是四面体,而是立方体的6个面.

这里发生了什么?如何将返回的单纯形式限制为仅仅是四面体?我用这个简单的案例来证明这个问题,所以我想要一个不适合这个问题的解决方案.

编辑

感谢Amro的回答,我能够解决这个问题,我可以在Matlab和Scipy之间找到一个简单的匹配.有两个因素在起作用.首先,正如所指出的,Matlab和Scipy使用不同的QHull选项.其次,QHull返回零容量的单纯形.Matlab删除了这些,Scipy没有.这在上面的例子中很明显,因为所有6个额外的单纯形都是立方体的零体积共面面.可以使用以下代码在N维中删除它们.

N = 3 # The dimensions of our points
options = 'Qt Qbb Qc' if N <= 3 else 'Qt Qbb Qc Qx' # Set the QHull options
tri = scipy.spatial.Delaunay(points, qhull_options = options).simplices
keep = np.ones(len(tri), dtype = bool)
for i, t in enumerate(tri):
    if abs(np.linalg.det(np.hstack((points[t], np.ones([1,N+1]).T)))) < 1E-15:
        keep[i] = False # Point is coplanar, we don't want to keep it
tri = tri[keep]
Run Code Online (Sandbox Code Playgroud)

我想应该解决其他条件,但我保证我的点已经没有重复,并且方向条件似乎对我能辨别的输出没有影响.

Amr*_*mro 4

比较 MATLAB 和 SciPy 函数的一些注释:

  • 根据 MA​​TLAB 文档,默认情况下它使用 Qt Qbb QcQhull 选项进行 3 维输入,而 SciPy使用 Qt Qbb Qc Qz.

  • 不确定这是否重要,但您的 NumPy 数组与 MATLAB 中创建的点的顺序不同ndgrid

事实上,如果您查看 中的 MATLAB 代码edit delaunayn.m,您可以看到执行了三个额外步骤:

  • 首先它合并重复点mergeDuplicatePoints(这对你来说不是问题)
  • 然后它强制点的方向约定(参见代码)
  • 最后从Qhull(作为MEX函数实现qhullmx)得到结果后,在几行代码上方有以下注释:

    去除可能因简并性的存在而产生的零体积单纯形。

由于该文件受版权保护,因此我不会在这里发布代码,但您可以检查一下。