Python 从Voronoi细分到形状多边形

Python 从Voronoi细分到形状多边形,python,gis,voronoi,shapely,Python,Gis,Voronoi,Shapely,根据一组点,我使用以下方法构建了Voronoi细分: 现在,我想从Voronoi算法创建的区域中构建一个。问题是多边形类需要一个逆时针顶点列表。虽然我知道如何解决,但我无法解决问题,因为这通常是我的结果: (重叠多边形)。以下是代码(一个随机示例): 我怎样才能解决这个问题 您实现的函数(order_vertices())在您的情况下不起作用,因为它只需要一个已排序的坐标序列,该坐标序列构建一个矩形,并反转多边形的方向(可能仅适用于矩形…)。 但是你有一个不有序的坐标序列 一般来说,不能从任意

根据一组点,我使用以下方法构建了Voronoi细分:

现在,我想从Voronoi算法创建的区域中构建一个。问题是多边形类需要一个逆时针顶点列表。虽然我知道如何解决,但我无法解决问题,因为这通常是我的结果:

(重叠多边形)。以下是代码(一个随机示例):


我怎样才能解决这个问题

您实现的函数(order_vertices())在您的情况下不起作用,因为它只需要一个已排序的坐标序列,该坐标序列构建一个矩形,并反转多边形的方向(可能仅适用于矩形…)。 但是你有一个不有序的坐标序列

一般来说,不能从任意非有序顶点序列构建多边形,因为凹多边形没有唯一的解决方案,如本例所示:

但是,如果您确定多边形始终是凸的,则可以使用以下代码构建凸壳:(目前已测试,对我有效)


也许你也可以用scipy来构建凸面外壳,但我无法测试它:

如果你只是在一组多边形之后,你不需要对点进行预排序来构建它们

scipy.spatial.Voronoi
对象具有一个
ridge\u顶点
属性,该属性包含构成Voronoi脊线的顶点索引。如果索引为
-1
,则脊线变为无穷大

首先从一些随机点开始构建Voronoi对象

将numpy导入为np
从scipy.spatical导入Voronoi,Voronoi_plot_2d
导入shapely.geometry
导入shapely.ops
点=np.随机.随机((10,2))
vor=Voronoi(点数)
voronoi图2d(vor)

您可以使用它来构建形状优美的线条字符串对象的集合

行=[
shapely.geometry.LineString(vor.vertices[line])
对于vor.ridge_顶点中的线
如果-1不一致
]
shapely.ops
模块具有返回shapely多边形对象生成器的

用于shapely.ops.polygonizate(行)中的多边形:
#对每个多边形做点什么

或者,如果希望从Voronoi细分所包围的区域形成单个多边形,则可以使用Shapely
One Ary_union
方法:

shapely.ops.uniary_联合(列表(shapely.ops.polygonizane(行)))

正如其他人所说,这是因为您必须根据索引从结果点正确地重建多边形。虽然您已经有了解决方案,但我想我应该提到还有另一个支持pypi的tesselation包,名为(免责声明:我是包维护者),其中voronoi函数返回完全为您构建的voronoi多边形

该库能够生成有序的坐标列表,您只需使用提供的索引列表:

import numpy as np
from scipy.spatial import Voronoi

...

ids = np.array(my_points_list)
vor = Voronoi(points)
polygons = {}
for id, region_index in enumerate(vor.point_region):
    points = []
    for vertex_index in vor.regions[region_index]:
        if vertex_index != -1:  # the library uses this for infinity
            points.append(list(vor.vertices[vertex_index]))
    points.append(points[0])
    polygons[id]=points

polygons
字典中的每个多边形都可以导出为geojson,也可以放入shapely,我能够在QGIS中正确地渲染它们,这看起来不像是顶点的逆时针排序。你确定你正确地实现了排序算法吗?@Kevin我想我正确地实现了它。。。我用一个例子更新了这个问题:生成图形的代码是什么?或者这是一个单独的例子?@Kevin,该代码生成了图形:)如何将形状文件与多边形一起保存?@ValerioD.Ciotti在多边形上使用
shapely.geometry.mapping
将它们转换为对象,然后使用类似于将geojson写入新形状文件的库。如果您被困在那里,请在.@ValerioD.Ciotti上提问,或者您可以从多边形生成
geopandas.GeoSeries
,并将其直接保存到shapefile中。您也可以直接使用
fiona
库,geopandas已经依赖该库。有关处理无限沃罗诺区域的方法,请参阅。
def order_vertices(l):
    mlat = sum(x[0] for x in l) / len(l)
    mlng = sum(x[1] for x in l) / len(l)

    # https://stackoverflow.com/questions/1709283/how-can-i-sort-a-coordinate-list-for-a-rectangle-counterclockwise
    def algo(x):
        return (math.atan2(x[0] - mlat, x[1] - mlng) + 2 * math.pi) % 2*math.pi

    l.sort(key=algo)
    return l

a = np.asarray(order_vertices([(9.258054711746084, 45.486245994138976),
 (9.239284166975443, 45.46805963143515),
 (9.271640747003861, 45.48987234571072),
 (9.25828782103321, 45.44377372506324),
 (9.253993275176263, 45.44484395950612),
 (9.250114174032936, 45.48417979682819)]))
plt.plot(a[:,0], a[:,1])
import numpy as np
from scipy.spatial import Voronoi

...

ids = np.array(my_points_list)
vor = Voronoi(points)
polygons = {}
for id, region_index in enumerate(vor.point_region):
    points = []
    for vertex_index in vor.regions[region_index]:
        if vertex_index != -1:  # the library uses this for infinity
            points.append(list(vor.vertices[vertex_index]))
    points.append(points[0])
    polygons[id]=points