我正在尝试使用scipy.spatial.Delaunay函数复制由Python中的Matlab delaunayn函数执行的N维Delaunay三角剖分.然而,虽然Matlab函数给了我想要和期望的结果,但是scipy给了我不同的东西.考虑到两者都是QHull库的包装器,我发现这很奇怪.我假设Matlab在其调用中隐式设置了不同的参数.我试图在他们两个之间复制的情况可以在Matlab’s documentation找到.
设置是在中心有一个点,如下所示.我提供的蓝线有助于形象化,但它们没有任何目的或意义.
我期望的三角测量结果是12个单纯形式(在Matlab示例中列出),如下所示.
然而,这个python等效产生“额外”的单纯形.
x = np.array([[-1,-1,-1],[-1,1],1,[1,[0,0]])
simp = scipy.spatial.Delaunay(x).simplices
返回的变量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]
>根据MATLAB文档,默认情况下它为uses Qt Qbb Qc Qhull选项进行三维输入,而SciPy uses Qt Qbb Qc Qz.
>不确定它是否重要,但是您的NumPy数组与在MATLAB中使用ndgrid创建的点的顺序不同.
实际上,如果你在编辑delaunayn.m中查看MATLAB代码,你可以看到执行了三个额外的步骤:
>首先它合并重复点mergeDuplicatePoints(在您的情况下这不是问题)
>然后它强制执行点的方向约定(参见代码)
>最后在从Qhull获得结果(实现为MEX函数qhullmx)之后,在几行代码上面有以下注释:
Strip the zero volume simplices that may have been created by the presence of degeneracy.