用 Python 创建 Voronoi 图

server/2024/12/23 1:20:57/

概述

最常见的空间问题之一是找到距离我们当前位置最近的兴趣点 (POI)。假设有人很快就会耗尽汽油,他/她需要在为时已晚之前找到最近的加油站,解决这个问题的最佳解决方案是什么?当然,驾驶员可以检查地图来找到最近的加油站,但如果该地区有多个加油站,并且他/她需要快速确定哪个加油站是最近的,则可能会出现问题。最好的解决方案是用多边形内的点来表示每个 POI。所以在多边形内,最近的 POI 肯定是多边形内的点。这些多边形称为 Voronoi 区域。

数据采集

在这个项目中,我根据 POI 数据在地图上创建 Voronoi 区域。所有 POI 数据都是随机选择的,而街道网络数据则借助 OSMnx 包从 OpenStreetMap 下载。

创建 Voronoi 区域

目前使用 Python 构建 Voronoi 区域的最简单方法是使用 geovoronoi 包。 Geovoronoi 是一个用于在地理区域内创建和绘制 Voronoi 区域的软件包。至于地图可视化,我选择 folium 包。

首先,我首先在地图周围创建随机点。

gdf = gpd.GeoDataFrame()
gdf = gdf.append({'geometry': Point(106.644085,-6.305286)}, ignore_index=True)
gdf = gdf.append({'geometry': Point(106.653261,-6.301309)}, ignore_index=True)
gdf = gdf.append({'geometry': Point(106.637751,-6.284774)}, ignore_index=True)
gdf = gdf.append({'geometry': Point(106.665062,-6.284598)}, ignore_index=True)
gdf = gdf.append({'geometry': Point(106.627582,-6.283521)}, ignore_index=True)
gdf = gdf.append({'geometry': Point(106.641365,-6.276593)}, ignore_index=True)
gdf = gdf.append({'geometry': Point(106.625972,-6.303643)}, ignore_index=True)

下一步是确定 Voronoi 区域的覆盖范围并将其保存到地理数据框中。

area_max_lon = 106.670929
area_min_lon = 106.619602
area_max_lat = -6.275227
area_min_lat = -6.309795lat_point_list = [area_min_lat, area_max_lat,area_max_lat,area_min_lat]
lon_point_list = [area_min_lon, area_min_lon, area_max_lon, area_max_lon]polygon_geom = Polygon(zip(lon_point_list, lat_point_list))
boundary = gpd.GeoDataFrame()
boundary = boundary.append({'geometry': polygon_geom}, ignore_index=True)

不要忘记将 gdf ​​和边界数据帧转换为 Web 墨卡托投影。

gdf.crs = {'init' :'epsg:3395'}
boundary.crs = {'init' :'epsg:3395'}

将边界几何数据帧转换为多边形和 POI 数据帧的并集转换为坐标数组。

boundary_shape = cascaded_union(boundary.geometry)
coords = points_to_coords(gdf.geometry)>

计算 Voronoi 区域。

poly_shapes, pts, poly_to_pt_assignments = voronoi_regions_from_coords(coords, boundary_shape)

在覆盖区域的边界内从 OpenStreetMap 创建图形。使用图表收集覆盖区域边界内的所有街道网络并将其保存到数据框中。

G = ox.graph_from_polygon(boundary_shape, network_type='all_private')
gdf_all_streets =  ox.graph_to_gdfs(G, nodes=False, edges=True,node_geometry=False, fill_edge_geometry=True)

创建新的数据框来收集每个 Voronoi 区域内的街道网络

gdf_streets_by_region = gpd.GeoDataFrame()
for x in range(len(poly_shapes)):gdf_streets = gpd.GeoDataFrame()gdf_streets['geometry'] = gdf_all_streets.intersection(poly_shapes[x])gdf_streets['voronoi_region'] = xgdf_streets = gdf_streets[gdf_streets['geometry'].astype(str) != 'LINESTRING EMPTY']gdf_streets_by_region = gdf_streets_by_region.append(gdf_streets)

下面是地图上 Voronoi 区域的可视化。

结论

地图看起来很棒!


http://www.ppmy.cn/server/18968.html

相关文章

GEM TSU Interface Details and IEEE 1588 Support

摘要:Xilinx ZNYQ ULTRASCALE MPSOC的GEM和1588的使用 对于FPGA来说,只需要勾选一些znyq的配置就行了,其余的都是软件的工作; 所有配置都勾选之后,最终会露出来的接口如下: GEM需要勾选的配置如下&#xf…

【C++】哈希思想

目录 哈希介绍: 一,位图 1-1,位图的认识 1-2,位图的简单实现 1-3,位图的应用 二,布隆过滤器 2-1,布隆过滤器的认识 2-2,布隆过滤器的简单实现 2-3,布隆过滤器的…

Android Glide 获取动图的第一帧

一、说明 Glide 可以加载 2 种动图,一种是 Gif 图,另一种是 Webp 动图。 有时候我们需要获取动图的第一帧,并以封面的形式显示,那该怎样获取呢? 二、获取 Webp 第一帧 我这儿的 Webp 显示用到了一个三方库&#xf…

从零入门区块链和比特币(第二期)

欢迎来到我的区块链与比特币入门指南!如果你对区块链和比特币感兴趣,但不知道从何开始,那么你来对地方了。本博客将为你提供一个简明扼要的介绍,帮助你了解这个领域的基础知识,并引导你进一步探索这个激动人心的领域。…

QT中基于TCP的网络通信

QT中基于TCP的网络通信 QTcpServer公共成员函数信号 QTcpSocket公共成员函数信号 通信流程服务器端通信流程代码 客户端通信流程代码 使用Qt提供的类进行基于TCP的套接字通信需要用到两个类: QTcpServer:服务器类,用于监听客户端连接以及和客…

基于streamlit快速部署机器学习项目(Public URL)

基于streamlit的AIGC项目前端展示 1.Streamlit 简介与入门1.1 安装 Streamlit1.2 开发Streamlit应用程序1.3 启动并运行1.3.1 本地运行1.3.2 部署 现在LLM技术发展迅速,很多人在学习的时候,都想展示效果,并且想部署在服务器上,但是…

WPF 资源基础

动态资源/静态资源 UI代码 <Window x:Class"WpfApp1.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.com/ex…

openjudge_2.5基本算法之搜索_200:Solitaire

题目 200:Solitaire 总时间限制: 5000ms 单个测试点时间限制: 1000ms 内存限制: 65536kB 描述 Solitaire is a game played on a chessboard 8x8. The rows and columns of the chessboard are numbered from 1 to 8, from the top to the bottom and from left to right resp…