You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Shapely多边形生成兼容OSMnx的自定义节点NetworkX图

问题描述

我们已有如下Shapely多边形对象:

from shapely import geometry

# (纬度, 经度)坐标
p1 = geometry.Point(-96.87,32.88)
p2 = geometry.Point(-96.77,33.00)
p3 = geometry.Point(-96.67,32.95)
p4 = geometry.Point(-96.65,32.84)
pointList = [p1, p2, p3, p4, p1]

# 创建多边形对象
p = geometry.Polygon([[p.x, p.y] for p in pointList])

通常我们会用OSMnx从该多边形生成真实路网的NetworkX图:

import osmnx as ox
G = ox.graph.graph_from_polygon(p, network_type='drive', simplify=False)

但现在需要生成虚拟路网:在多边形内随机分布指定数量的节点,每个节点至少与指定数量的最近邻居相连,生成的图需兼容OSMnx功能(如可视化),需实现如下函数:

def f_generate_plain_polygon(p, number_of_nodes, min_number_of_connection_for_each_node):
    ...

也可通过指定节点间距替代节点数来实现。


解决方案

实现思路

  1. 在多边形边界范围内生成随机采样点,筛选出位于多边形内部的节点
  2. 计算每个节点到其他节点的欧氏距离,选取最近的指定数量邻居
  3. 构建NetworkX有向图,添加OSMnx兼容的节点/边属性,确保可直接使用OSMnx工具

完整代码实现

import numpy as np
import networkx as nx
import osmnx as ox
import matplotlib.pyplot as plt
from shapely.geometry import Point, Polygon

def f_generate_plain_polygon(p, number_of_nodes, min_number_of_connection_for_each_node):
    # 获取多边形的边界范围
    min_x, min_y, max_x, max_y = p.bounds
    
    # 生成多边形内的随机节点
    nodes = []
    while len(nodes) < number_of_nodes:
        # 生成随机坐标
        x = np.random.uniform(min_x, max_x)
        y = np.random.uniform(min_y, max_y)
        point = Point(x, y)
        # 验证点是否在多边形内部
        if p.contains(point):
            nodes.append((x, y))
    
    # 初始化兼容OSMnx的有向图
    G = nx.DiGraph()
    
    # 添加节点并设置OSMnx所需属性
    for idx, (x, y) in enumerate(nodes):
        G.add_node(
            idx,
            x=x,
            y=y,
            osmid=idx,
            ref=None,
            highway=None,
            node_id=idx
        )
    
    # 计算节点间距离并添加边
    nodes_array = np.array(nodes)
    for i in range(number_of_nodes):
        # 计算当前节点到所有其他节点的欧氏距离
        distances = np.linalg.norm(nodes_array - nodes_array[i], axis=1)
        # 按距离排序,排除节点自身
        sorted_neighbor_indices = np.argsort(distances)[1:]
        # 选取前N个最近邻居(N为指定的最小连接数)
        target_neighbors = sorted_neighbor_indices[:min_number_of_connection_for_each_node]
        
        # 添加双向边(模拟路网双向通行)
        for neighbor_idx in target_neighbors:
            edge_length = distances[neighbor_idx]
            # 正向边
            G.add_edge(
                i,
                neighbor_idx,
                osmid=f"{i}-{neighbor_idx}",
                length=edge_length,
                highway='unclassified',
                oneway=False
            )
            # 反向边
            G.add_edge(
                neighbor_idx,
                i,
                osmid=f"{neighbor_idx}-{i}",
                length=edge_length,
                highway='unclassified',
                oneway=False
            )
    
    # 移除孤立节点
    ox.utils_graph.remove_isolated_nodes(G)
    
    return G

# 测试示例
if __name__ == "__main__":
    # 创建示例多边形
    p1 = Point(-96.87,32.88)
    p2 = Point(-96.77,33.00)
    p3 = Point(-96.67,32.95)
    p4 = Point(-96.65,32.84)
    pointList = [p1, p2, p3, p4, p1]
    p = Polygon([[point.x, point.y] for point in pointList])
    
    # 生成含60个节点、每个节点至少3个连接的虚拟路网
    G = f_generate_plain_polygon(p, number_of_nodes=60, min_number_of_connection_for_each_node=3)
    
    # 使用OSMnx可视化
    fig, ax = ox.plot_graph(
        G,
        show=False,
        close=False,
        edge_color='black',
        bgcolor='w',
        edge_alpha=0.5,
        node_color='black',
        node_size=30
    )
    plt.show()

关键说明

  • 节点有效性:通过p.contains(point)确保所有生成的节点都在目标多边形内部
  • OSMnx兼容性:为节点添加x、y、osmid,为边添加length、highway等属性,完全适配OSMnx的可视化和分析接口
  • 双向边设计:生成双向边模拟真实路网的通行逻辑,符合OSMnx对路网图的默认要求
  • 节点间距替代方案:若要改用节点间距控制生成,可先按间距生成网格点,再对每个网格点添加随机扰动,最终筛选多边形内的节点即可

内容的提问来源于stack exchange,提问作者illuminato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 03:25:21