如何用R的sf与ggplot2重绘OpenStreetMap矢量数据?
刚好我之前做过类似的需求,用sf和ggplot2完全可以复刻出Stamen Toner风格的矢量地图,给你一步步拆解方案:
用sf + ggplot2 复刻Stamen Toner风格的OSM矢量地图
第一步:读取Overpass获取的OSM矢量数据
假设你已经通过Overpass拿到了矢量数据(比如GeoJSON或OSM格式),先用sf包读取;如果还没执行查询,也可以用osmdata包直接对接Overpass API:
library(sf) library(ggplot2) library(osmdata) # 定义你的边界框(和之前get_map用的bb一致) bb <- c(left = xxx, bottom = xxx, right = xxx, top = xxx) # 直接通过Overpass API获取所需要素(道路、建筑、水域等) osm_query <- opq(bbox = bb) %>% add_osm_feature(key = "highway") %>% # 获取所有道路要素 add_osm_feature(key = "building") %>% # 获取建筑要素 add_osm_feature(key = "natural", value = "water") # 获取水域要素 osm_data <- osmdata_sf(osm_query)
如果是已经下载好的本地文件,直接用st_read()读取即可:
osm_data <- st_read("your_overpass_output.geojson")
第二步:分层绘制匹配Toner风格
Stamen Toner是高对比度黑白简约风格,我们通过图层顺序和样式参数来复刻:
ggplot() + # 1. 绘制水域(填充黑色,无轮廓) geom_sf(data = osm_data$osm_multipolygons[osm_data$osm_multipolygons$natural == "water",], fill = "black", color = NA) + # 2. 绘制建筑(填充黑色,无轮廓) geom_sf(data = osm_data$osm_buildings, fill = "black", color = NA) + # 3. 绘制主干道(粗黑线条) geom_sf(data = osm_data$osm_highways[osm_data$osm_highways$highway %in% c("motorway", "primary", "secondary"),], color = "black", linewidth = 1.2) + # 4. 绘制次干道(细黑线条) geom_sf(data = osm_data$osm_highways[osm_data$osm_highways$highway %in% c("tertiary", "residential"),], color = "black", linewidth = 0.6) + # 5. 绘制小路(浅灰细线条,可选) geom_sf(data = osm_data$osm_highways[osm_data$osm_highways$highway %in% c("footway", "path"),], color = "#666666", linewidth = 0.2) + # 设置主题:纯白背景+无坐标轴网格,贴合Toner风格 theme_void() + theme(plot.background = element_rect(fill = "white", color = NA)) + # 锁定视图范围为你的边界框,避免自动扩展 coord_sf(xlim = c(bb["left"], bb["right"]), ylim = c(bb["bottom"], bb["top"]), expand = FALSE)
第三步:细节优化(可选)
- 添加道路名称标签:
geom_sf_text(data = osm_data$osm_highways[osm_data$osm_highways$name != "",], aes(label = name), size = 3, color = "black", check_overlap = TRUE)
- 调整图层顺序:比如把建筑放在道路下方(只需要调换
geom_sf的顺序即可) - 微调样式参数:根据实际视觉效果调整线宽、颜色深浅,完全匹配Stamen Toner的质感
内容的提问来源于stack exchange,提问作者wdkrnls
相关产品推荐
相关产品推荐

