我在使用scipy的Voronoi功能时遇到了麻烦。我已经按照第二个例子,但是当我在3d中执行类似的例子时,并不是所有的ridge_points都被计算出来。我的数据是[0,2] x [0,2] x [0,2]中的27个点:
points = np.array([
# bottom plane
[0,2,0], [1,2,0], [2,2,0],
[0,1,0], [1,1,0], [2,1,0],
[0,0,0], [1,0,0], [2,0,0],
# middle plane
[0,2,1], [1,2,1], [2,2,1],
[0,1,1], [1,1,1], [2,1,1],
[0,0,1], [1,0,1], [2,0,1],
# top plane
[0,2,2], [1,2,2], [2,2,2],
[0,1,2], [1,1,2], [2,1,2],
[0,0,2], [1,0,2], [2,0,2]
])
vor = Voronoi(points)
print vor.ridge_points
# outputed
array([[ 4, 7],
[ 4, 5],
[ 4, 3],
[ 4, 1],
[ 4, 13],
[ 3, 12],
[ 7, 16],
[15, 12],
[15, 16],
[ 9, 12],
[ 9, 10],
[ 1, 10],
[12, 21],
[12, 13],
[23, 14],
[23, 22],
[14, 17],
[14, 11],
[14, 5],
[14, 13],
[22, 19],
[22, 21],
[22, 13],
[22, 25],
[17, 16],
[11, 10],
[25, 16],
[16, 13],
[13, 10],
[19, 10], dtype=int32)
我注意到角落上的点:
points[0] = array([0, 2, 0])
points[2] = array([2, 2, 0])
points[6] = array([0, 0, 0])
points[8] = array([2, 0, 0])
points[18] = array([0, 2, 2])
points[20] = array([2, 2, 2])
points[24] = array([0, 0, 2])
points[26] = array([2, 0, 2])
没有任何脊点。我会假设(像2d情况一样)角落会有脊点。例如,我假设点[6] = [0,0,0]将具有[1,0,0],[0,1,0]和[0,0,1]的脊点。这是不可能用scipy计算或我一直在考虑这个错误?
答案 0 :(得分:1)
Scipy使用Qhull进行Delaunay / Voronoi / Convexhull计算。 ridge_points
中包含的数据是qvoronoi Fv
报告的数据,尽管脊不一定按相同的顺序列出。 (作为支票:https://gist.github.com/pv/2f756ec83cdf242ce691)
Fv
(http://www.qhull.org/html/qh-optf.htm#Fv2)的Qhull文档提到了一个似乎与此相关的警告:
选项' Fv'不列出需要多个中点的脊。例如,球面点的Voronoi图列出零脊(例如,< rbox 10 s | qvoronoi Fv Qz')。其他示例是矩形网格的Voronoi图(例如,' rbox 27 M1,0 | qvoronoi Fv')或具有矩形网格的点集(例如,' rbox P4,4,4 P4,2,4 P2,4,4 P4,4,2 10 | qvoronoi Fv')。两种情况都会错过角落处的无界光线。为了确定这些脊,用大立方体围绕点(例如,< rbox 10 s c G2.0 | qvoronoi Fv Qz')。立方体需要足够大以限制原始点集的所有Voronoi区域。请报告任何其他错过的案例。如果您可以正式描述这些案例或编写代码来处理它们,请发送电子邮件至qhull@qhull.org。
文本中提到的rbox 27 M1,0
与示例中的点集完全相同(按不同顺序)。
通常,Qhull在处理几何退化方面存在问题,例如在矩形网格中发生。一般的解决方法是设置qhull_options="QJ"
,它告诉它在数据点添加随机扰动,直到解析退化。这通常会产生tesselations / voronoi图表,其中包含几个额外的单纯形/脊,但可能会解决此类问题。
答案 1 :(得分:0)
我也遇到了同样的问题。然后我使用 Delaunay 获取 3D 中的所有 rigde 点。如下:
def find_neighbors(tess):
"""
Parameters
----------
tess : Delaunay
Returns
-------
neighbors : neighbors in defaultdict type
"""
neighbors = defaultdict(set)
for simplex in tess.simplices:
for idx in simplex:
other = set(simplex)
other.remove(idx)
neighbors[idx] = neighbors[idx].union(other)
return neighbors
import scipy.spatial
from collections import defaultdict
x_list = np.random.random(8)
y_list = np.random.random(8)
z_list = np.random.random(8)
tri = scipy.spatial.Delaunay(np.array([[x,y,z] for x,y,z in zip(x_list, y_list, z_list)])) # create the Delaunay triangles
print(find_neighbors(tri))