首页 > 解决方案 > 按路线类型提取 Open Street Map 方式 ID 的交叉口计数

问题描述

编辑添加了额外的细节

我有 2,061 个开放街道地图 ( OSM ) 路段的 shapefile。我的 shapefile 中的每个段都由其 OSM Way ID 标识。

这是我的数据中五个段的示例:

data = 
structure(list(osm_id = structure(1:5, .Label = c("17990110", 
"17993246", "17994983", "17994985", "17995338"), class = "factor"), 
    name = structure(c(1L, 3L, 4L, 5L, 2L), .Label = c("109th Avenue Northeast", 
    "85th Avenue Northeast", "Bunker Lake Boulevard Northeast", 
    "Foley Boulevard", "Northdale Boulevard Northwest"), class = "factor")), row.names = c(NA, 
5L), class = c("sf", "data.frame"))

对于这 2061 个路段中的每一个路段,我想分别计算每种道路类型(住宅、主要、第三...)与其他道路的交叉口数量。

例如,这条 OSM 路与其他 27 条路相交,其中 11 条为“住宅”,其中 3 条为“二级”高速公路。

这是次要的分析,但最终,对于多种类型道路连接的交叉口,我将选择“最大”类型的道路。例如,该节点连接了一条服务道路和一条住宅道路;我想选择住宅道路道路。我想我可以为此创建自己的层次结构列表并在以后处理它。

我正在尝试使用 R Open Sci 包osmdata

到目前为止,我可以使用 osmdata 到达#2(信号交叉口):

node_dat <- opq_osm_id(type = "node", id = '17990110')%>%
  opq_string()%>%
  osmdata_sf

node_dat_pts <- node_dat$osm_points

nrow(node_dat_pts[node_dat_pts$traffic_signals %in% "signal",])

这表明沿着这个 OSM 段有三个交通信号。(尽管实际上只有两个信号交叉口——两个信号与分开的高速公路相关联……但这可能是另一个问题)。

我是 R 本地人,这就是 osmdata 包对我如此有吸引力的原因,但我愿意探索 Overpass API 中的查询。TBH 我发现关于如何在网站上获取交叉节点的示例不太适用——而且我不清楚如何将此过程扩展到我拥有的 2000 多个方式 ID 的长列表(但如果文档或存在示例,请指出它)。

我也愿意探索 Python 中的其他工具库;Python osmnx 包似乎具有用于计算“交叉点密度”的优秀工具,但对于指定的多边形,如城市边界,并且似乎没有通过方式或节点 ID 在 Python 中创建调用的功能。

我也知道我可能可以在 ArcGIS 或 QGIS 中执行此操作,但是因为我的数据库中已经有了这些 OSM ID,所以为大都市地区加载一个完整的交叉路口形状文件并做一些事情似乎是一种浪费缓冲过程以获取我需要的信息。另外,如果我有一个方便的脚本来通过方式或节点 ID 提取一些信息,我可以更轻松地扩展我提取的数据类型,以获取为 OSM 元素记录的其他重要信息的花絮。

感谢空间数据社区!

标签: openstreetmapoverpass-apiropenscidodgr

解决方案


始终标记交通信号"highway" = "traffic_signals",但也可以使用 的键标记单个节点"traffic_signals"。因此,获取所有交通信号的第一步可以这样完成:

library(osmdata)
hw <- opq("minneapolis") %>%
    add_osm_feature(key = "highway") %>%
    osmdata_sf()
signal_nodes <- opq("minneapolis") %>%
    add_osm_feature(key = "traffic_signals") %>%
    osmdata_sf()
index <- which (!is.na (hw$osm_points$traffic_signals) |
                grepl ("traffic_signals", hw$osm_points$highway)) # grepl because can be "traffic_signals:<value>"
signal_node_ids <- unique (c (signal_nodes$osm_points$osm_id, hw$osm_points$osm_id [index]))

然后保存描述交通信号的节点的所有 OSM ID 值。

获得交叉点密度的一种直接方法是将sf高速公路的表示转换为dodgr网络,这很简单data.frame,每一行都是网络边缘。该步骤将诸如环形交叉路口之类的poly2line严格多边形转换为对象,而该调用仅将网络简化为交汇点。sflinestringdodgr_contract_graph()

library(dodgr)
hw <- osm_poly2line(hw)$osm_lines %>%
    weight_streetnet(keep_cols = "highway", wt_profile = 1) %>% # wt_profile irrelevant here
    dodgr_contract_graph()

table(net$highway)会给你不同类型的高速公路的频率。然后,您可以检查特定类型的结频率,如下所示

net_footway <- net[net$highway == "footway", ]
table(table(c(net_footway$from_id, net_footway$to_id)))

值为 1 表示单向终端节点;值为 2 表示双向终端节点;值 4 表示两条边之间的交叉点;等等。那张桌子增加到 14 条,因为人行道可能相当复杂,而且明尼阿波利斯某处显然有7 条人行道的交汇处。这些 ID 是 OSM id,因此您可以轻松检查其中哪些在signal_node_ids值中以确定哪​​些具有交通信号。


需要解决的剩余问题:

  1. 单一定义"highway"类型之间的交集很容易,但不同类型之间的交集需要对这段代码进行更复杂的修改。尽管很简单,但您需要始终如一地设置dodgr data.frame边缘指向的子集:$from_id -> $to_id.
  2. 将信号与特定路口相关联可能需要某种空间缓冲,因为正如您所建议的那样,单个路口可能有多个节点"traffic_signals"。请注意,没有“正确”的方法可以做到这一点,因为例如,交叉路口可能对行人和汽车有单独的信号,并且决定是否将这些信号视为“相同”的信号总是需要一定程度的主观性。

推荐阅读