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

基于Python的OSMnx库查找距离边指定范围的最近点

解决OSMnx中点与边的关联及半径范围统计问题

嘿,我来帮你搞定这个需求!咱们一步步拆解,结合OSMnx和Shapely就能轻松实现你要的功能——把经纬度点关联到指定边,筛选出半径范围内的点,还能可视化统计。

核心思路

你提到已知边连接的节点经纬度,那这条边其实就是两个节点之间的线段(OSMnx里用LineString几何对象表示)。我们需要:

  1. 用节点坐标创建边的几何对象
  2. 计算每个点到这条边的距离(转成米为单位更准确)
  3. 筛选出半径范围内的点并统计数量
  4. 可视化绘制边、点和半径圆

步骤1:创建边的几何对象

首先,把已知的两个节点经纬度转换成Shapely的LineString。注意Shapely的坐标顺序是**(经度, 纬度)**,和我们常用的(lat, lon)反过来,别搞混了!

from shapely.geometry import LineString

# 替换成你实际的节点经纬度
node1_lon, node1_lat = -122.4194, 37.7749  # 节点1:lon在前,lat在后
node2_lon, node2_lat = -122.4074, 37.7817  # 节点2

# 创建边的几何对象
edge_geom = LineString([(node1_lon, node1_lat), (node2_lon, node2_lat)])

如果你的边是从OSMnx的路网图(graph)里来的,其实可以直接提取边的几何,不用手动创建:

import osmnx as ox

# 假设你已经有了路网图G,u和v是边的两个节点ID
edge_geom = G.edges[(u, v, 0)]['geometry']  # 第三个参数是边的索引,通常为0

步骤2:筛选半径范围内的点

因为WGS84坐标系(经纬度)的距离是度数,没法直接用米来判断,所以我们先把几何对象投影到UTM坐标系(自动适配所在区域,单位是米)。然后遍历所有点,计算到边的距离,筛选出符合条件的点。

import osmnx as ox
from shapely.geometry import Point

# 替换成你的点列表,格式是[(lat1, lon1), (lat2, lon2), ...]
points_list = [(37.776, -122.415), (37.778, -122.412), (37.779, -122.410)]

# 把边的几何投影到UTM坐标系,得到米为单位的几何和对应的CRS
edge_geom_utm, crs = ox.projection.project_geometry(edge_geom, to_crs=None)  # to_crs=None自动选UTM

# 设置你的半径(单位:米)
radius_x = 50  # 比如50米

# 筛选符合条件的点
nearby_points = []
for lat, lon in points_list:
    # 创建点的几何对象(注意坐标顺序是lon, lat)
    point_geom = Point(lon, lat)
    # 把点投影到同一个UTM坐标系
    point_geom_utm, _ = ox.projection.project_geometry(point_geom, to_crs=crs)
    # 计算点到边的距离(米)
    distance = point_geom_utm.distance(edge_geom_utm)
    # 判断是否在半径内
    if distance <= radius_x:
        nearby_points.append((lat, lon))

# 统计数量
print(f"距离目标边{radius_x}米内的点共有:{len(nearby_points)}个")

步骤3:可视化绘制

用Matplotlib把边、所有点、附近的点以及半径圆画出来,直观展示结果:

import matplotlib.pyplot as plt

# 把所有点和附近的点转换成UTM坐标
all_points_utm = [ox.projection.project_geometry(Point(lon, lat), to_crs=crs)[0] for lat, lon in points_list]
nearby_points_utm = [ox.projection.project_geometry(Point(lon, lat), to_crs=crs)[0] for lat, lon in nearby_points]

# 创建画布
fig, ax = plt.subplots(figsize=(10, 10))

# 绘制目标边
x_edge, y_edge = edge_geom_utm.xy
ax.plot(x_edge, y_edge, color='darkblue', linewidth=3, label='目标边')

# 绘制所有点(灰色)
for p in all_points_utm:
    ax.scatter(p.x, p.y, color='gray', s=15, alpha=0.5)

# 绘制附近的点(红色)和对应半径圆
for idx, p in enumerate(nearby_points_utm):
    ax.scatter(p.x, p.y, color='crimson', s=30, label='范围内的点' if idx == 0 else "")
    # 绘制半径圆
    circle = plt.Circle((p.x, p.y), radius_x, color='crimson', fill=False, linestyle='--', linewidth=1.5)
    ax.add_patch(circle)

# 设置绘图样式
ax.legend()
ax.set_aspect('equal')  # 保持坐标比例,避免圆变椭圆
plt.title(f"目标边周围{radius_x}米范围内的点分布")
plt.show()

小提示

  • 如果你的点数量特别多,可以用GeoPandas把点转成GeoDataFrame,然后用空间查询批量计算,效率更高。
  • 确保所有几何对象都在同一个坐标系下计算距离,UTM是最适合米级距离计算的选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:10:20