Openstreetmap 下载路网数据

  • Openstreetmap 下载路网数据的备忘

  • 资料来源:

    https://zhuanlan.zhihu.com/p/141740446
    https://github.com/gboeing/osmnx

  • 更新

    1
    2022.01.11 初始

导语

因为项目原因,必须要用到路网数据,只能自己找…

一番 google 后发现 公开的路网数据仅 osm 一家.

前排风险提示:

  • osm 地图在边界问题上与中国官方立场不同
    • 项目任何涉及大比例缩略图 / 国界线 等情况时,一定要记得换源.不要埋下风险点,这个风险点等级还不低,特别是在现在的大环境下.
    • 路网等仅涉及城市级别一般无问题.
  • OSM 数据均为 WGS 坐标
  • OSM 的道路等级可能与国内常见分类不同,有细致需求,请详细对比后使用.

需求

  • 下载某个地区(例如上海)的路网数据
  • 要能过滤掉等级比较低道路(例如小区内道路)
  • 需要转换成 GIS 常见格式

下载路网数据

目前从 osm 下载路网数据有这么几个途径

  • osm 网页端矩形框选取导出:

    • 需要明确范围且区域较小时使用
    • 限制节点在 50000 个
    • 还有一个类似的 [overpass-turbo](https://overpass-turbo.eu/
  • overpass-api 下载

    • 网页矩形选择能干的,也能干.
    • 包括分城市下载,没有节点总数限制.
    • 如果不是用 osmnx 下载,那是首选了.
  • osm 星球 下载全球数据,几十G.

    • 一般不用
  • geofabrik 提供以国家/一部分城市为单位的数据

    • 下载全国数据,这个最方便
    • china 数据大约 823 MB
  • osmnx python 包下载 osm 数据

    • 各类分类数据+过滤+格式转换
    • 项目以 python 为主,自然是选这个了.

osmnx

osmnx 提供了非常方便的 py 下载 osm 数据的选择.

  • 官方文档
  • 官方例程
  • 如果在项目中使用,需要标明引用 Boeing, G. 2017. "[OSMnx: New Methods for Acquiring, Constructing, Analyzing, and Visualizing Complex Street Networks](https://geoffboeing.com/publications/osmnx-complex-street-networks/)." _Computers, Environment and Urban Systems_ 65, 126-139. doi:10.1016/j.compenvurbsys.2017.05.004

下面的例子以下载上海地区路网为例

osm 路网等级

  • 参考 Key:highway
  • 我们需要下载的是 tertiary 及以上等级的路网数据

主要使用 osmnx.graph.graph_from_place 函数

  • 我们需要传入 3 个参数
    • place: 支持拼音,这里就是 Shanghai, China
    • network_type: 下载的地图种类,路网数据所以是 drive
    • custom_filter: 自定义的过滤器,这里想要的是 tertiary 及以上等级
      • ["highway"~"motorway|trunk|primary|secondary|tertiary"]
      • highway 下面的 motorway 到 tertiary.
  • 其他细节见 官网文档
  • custom-filters 的官方示例
1
2
3
4
5
6
7
place = "Shanghai, China"
cf = '["highway"~"motorway|trunk|primary|secondary|tertiary"]' # 不下载 村镇道路
G = ox.graph_from_place(place,
network_type="drive",
which_result=2,
custom_filter=cf)

整个过程大概 4-5 分钟,之后调用 save_graphml 保存到本地

1
2
3
4
# Gfile 为保存到本地的路径
ox.save_graphml(G, Gfile)
# 相对应的加载就是 load_graphml
#G = ox.load_graphml(Gfile)

一般而言某个城市的路网数据在 几十MB 量级.

转换 shp

下面这段转换代码来自 fmm-examples#1-download_network.ipynb

  • 毕竟下载路网数据就是要到 fmm 中用啊
  • 至于 fmm 😔,还有不少坑..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
path = "./"
filep_nodes = os.path.join(path, "nodes.shp")
filep_edges = os.path.join(path, "edges.shp")

def stringify_nonnumeric_cols(gdf):#转换数据类型
import pandas as pd
for col in (c for c in gdf.columns if not c == "geometry"):#除 geometry 外的所有列
if not pd.api.types.is_numeric_dtype(gdf[col]): #如果不是数字类型
gdf[col] = gdf[col].fillna("").astype(str) #全部转换为字符串
return gdf

gdf_nodes, gdf_edges = ox.graph_to_gdfs(G)
gdf_nodes = stringify_nonnumeric_cols(gdf_nodes)
gdf_edges = stringify_nonnumeric_cols(gdf_edges)

gdf_edges["fid"] = np.arange(0, gdf_edges.shape[0], dtype='int') #增加 fid 列

gdf_nodes.to_file(filep_nodes, encoding="utf-8")
gdf_edges.to_file(filep_edges, encoding="utf-8")

正常执行完毕后会在对应路径生成 node + edge 文件.