【问题标题】:Get point associated with Voronoi region (scipy.spatial.Voronoi)获取与 Voronoi 区域相关的点 (scipy.spatial.Voronoi)
【发布时间】:2015-08-14 23:02:01
【问题描述】:

我正在使用 scipy.spatial.Voronoi 函数生成一个简单的 2D Voronoi 细分。我使用点的随机 2D 分布(参见下面的 MCVE)。

我需要一种方法来遍历每个定义的区域(由scipy.spatial.Voronoi 定义)并获取与其关联的点的坐标(即:所述区域包围的点)。

问题是为N 点定义了N+1 区域(多边形),我不确定这意味着什么。

这是一个在到达最后一个区域时会失败的 MCVE:

from scipy.spatial import Voronoi
import numpy as np

# Generate random data.
N = 10
x = [np.random.random() for i in xrange(N)]
y = [np.random.random() for i in xrange(N)]
points = zip(x, y)

# Obtain Voronoi regions.
vor = Voronoi(points)

# Loop through each defined region/polygon
for i, reg in enumerate(vor.regions):

    print 'Region:', i
    print 'Indices of vertices of Voronoi region:', reg
    print 'Associated point:', points[i], '\n'

我不明白的另一件事是为什么存储了空的vor.regions?根据文档:

regions:形成每个 Voronoi 区域的 Voronoi 顶点的索引。 -1 表示 Voronoi 图之外的顶点。

空白区域是什么意思?


添加

我尝试了point_region 属性,但显然我不明白它是如何工作的。它返回points 列表范围之外的索引。例如:在上面的 MCVE 中,它总是会显示一个索引 10 用于 10 个点的列表,这显然超出了范围。

【问题讨论】:

  • Voronoi 实例有一个 point_region 属性,它完全符合您的要求。 Read the docs!
  • @Jaime 我确实尝试过该属性,请查看我添加到问题中的内容。

标签: python scipy voronoi


【解决方案1】:

第一个问题:

问题是为 N 个点定义了 N+1 个区域(多边形),我不确定这意味着什么。

这是因为您的 vor.regions 将始终有一个空数组。 像

    [[],[0, 0],[0, 1],[1, 1]]

这和你的第二个问题有关:

我不明白的另一件事是为什么存储了空的 vor.regions?根据文档:区域:形成每个 Voronoi 区域的 Voronoi 顶点的索引。 -1 表示 Voronoi 图之外的顶点。 空白区域是什么意思?

默认情况下,Voronoi() 使用启用了选项“Qbb Qc Qz Qx”的 QHull (qhull.org/html/qvoronoi.htm)。这会插入一个“无限远点”,用于提高循环输入的精度。因此,作为“假”点,它没有区域。如果你想摆脱这种情况,请尝试删除 Qz 选项:

vor = Voronoi(points, qhull_options='Qbb Qc Qx')

【讨论】:

    【解决方案2】:

    我误读了文档。它说:

    point_region:每个输入点Voronoi区域的索引。

    我使用point_region 就好像它是:“每个Voronoi 区域输入点的索引”。

    而不是使用:

    points[i]
    

    每个区域的正确点坐标可以通过以下方式获得:

    np.where(vor.point_region == i)[0][0]
    

    【讨论】:

    • 你知道为什么某些regions 是空的吗?这个documentation 说“请注意,由于与上面的 Delaunay 三角剖分类似的数值精度问题,Voronoi 区域可能比输入点少。”所以我猜这意味着qhull使用Delaunay计算Voronoi?并且“这种退化不仅可能是因为重复的点,还可能因为更复杂的几何原因,即使在乍一看似乎表现良好的点集中也是如此”
    • 但是虽然我已经了解了如何解决这个问题,但我仍然很困惑这些解决方案是给你真正的答案还是只是让“regions”不为空。我会继续寻找。也许就我而言,我只会丢弃给出空白区域的点
    • 不幸的是,自从我在研究中使用 Voronoi 区域以来已经有一段时间了,但我最终并没有真​​正使用它们,所以我无法让您了解正在发生的事情。也许您可以在math.stackexchange.com 询问,因为这似乎是与 Voronoi 区域的属性相关的问题,而不是它在 Scipy 中的实现?
    • 感谢您的快速回答。我相信事实恰恰相反,哈哈。 Voronoi 应该始终有一个与给定点相关联的区域,只要该点不是重复的。好像和qhull的实现有关系
    • 我希望@aqueiros 的回答是正确的,这些空白区域只是属于在无穷远处添加的点
    【解决方案3】:

    这里有一个解决方案:

    import numpy as np
    from scipy.spatial import Voronoi
    import matplotlib.pyplot as plt
    from plotutils_moje import voronoi_plot_2d
    
    
    class VoronoiRegion:
        def __init__(self, region_id):
            self.id = region_id
            self.vertices = []
            self.is_inf = False
            self.point_inside = None
    
        def __str__(self):
            text = f'region id={self.id}'
            if self.point_inside:
                point_idx, point = self.point_inside
                text = f'{text}[point:{point}(point_id:{point_idx})]'
            text += ', vertices: '
            if self.is_inf:
                text += '(inf)'
            for v in self.vertices:
                text += f'{v}'
            return text
    
        def __repr__(self):
            return str(self)
    
        def add_vertex(self, vertex, vertices):
            if vertex == -1:
                self.is_inf = True
            else:
                point = vertices[vertex]
                self.vertices.append(point)
    
    def voronoi_to_voronoi_regions(voronoi):
        voronoi_regions = []
    
        for i, point_region in enumerate(voronoi.point_region):
            region = voronoi.regions[point_region]
            vr = VoronoiRegion(point_region)
            for r in region:
                vr.add_vertex(r, voronoi.vertices)
            vr.point_inside = (i, voronoi.points[i])
            voronoi_regions.append(vr)
        return voronoi_regions
    
    
    points = np.array([[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]])
    vor = Voronoi(points)
    regions = voronoi_to_voronoi_regions(vor)
    for r in regions:
        print(r)
    

    sample 的结果:

    region id=1[point:[0. 0.](point_id:0)], vertices: (inf)[0.5 0.5]
    region id=3[point:[0. 1.](point_id:1)], vertices: (inf)[0.5 1.5][0.5 0.5]
    region id=2[point:[0. 2.](point_id:2)], vertices: (inf)[0.5 1.5]
    region id=8[point:[1. 0.](point_id:3)], vertices: (inf)[1.5 0.5][0.5 0.5]
    region id=7[point:[1. 1.](point_id:4)], vertices: [0.5 0.5][0.5 1.5][1.5 1.5][1.5 0.5]
    region id=9[point:[1. 2.](point_id:5)], vertices: (inf)[1.5 1.5][0.5 1.5]
    region id=6[point:[2. 0.](point_id:6)], vertices: (inf)[1.5 0.5]
    region id=4[point:[2. 1.](point_id:7)], vertices: (inf)[1.5 1.5][1.5 0.5]
    region id=5[point:[2. 2.](point_id:8)], vertices: (inf)[1.5 1.5]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-22
      • 2014-01-14
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 1970-01-01
      • 2021-06-25
      相关资源
      最近更新 更多