如何利用OSMnx绘制各类OSM水体(适配全球任意区域)
解决OSMnx获取全球海岸/岛屿水体数据的问题
问题背景
我正在用Python脚本绘制地图的不同图层(水体、草地、岩石等),通过OSMnx调用OpenStreetMap数据,获取岩石图层的代码如下:
nature['rock'] = ox.features_from_point((latitude, longitude), dist=dist, tags={'natural': ['bare_rock', 'rock', 'scree']})
但目前无法获取全球任意区域(包括岛屿、海岸)的所有水体数据并统一绘制:
- 尝试过
tags={'natural': ['water', 'bay']}、tags={'natural': 'coastline'}标签,单独或组合调用后合并均无效 - prettymaps包在海岸、岛屿场景下表现不佳
预期效果:
实际效果:
解决方案
1. 用更全面的标签覆盖所有水体类型
OSM中海岸和岛屿区域的水体涉及多种标签组合,仅用natural=water或natural=coastline会遗漏部分数据。建议使用以下标签集合来覆盖内陆水、海域、海湾等:
# 覆盖各类水体类型的标签 water_tags = { 'natural': ['water', 'bay'], 'water': ['sea', 'ocean', 'lake', 'bay', 'lagoon'], 'waterway': ['river', 'stream', 'canal'] # 可选,若需要包含河流等线性水体 } # 获取水体数据 nature['water'] = ox.features_from_point((latitude, longitude), dist=dist, tags=water_tags)
2. 处理海岸线与水体多边形的合并
natural=coastline是线性边界,无法直接填充颜色。需要单独获取海域多边形并与其他水体数据合并:
import pandas as pd import geopandas as gpd # 获取海域多边形 sea_polygons = ox.features_from_point( (latitude, longitude), dist=dist, tags={'natural': 'water', 'water': ['sea', 'ocean']} ) # 合并所有水体数据 all_water = pd.concat([nature['water'], sea_polygons], ignore_index=True) # 修复几何错误并合并重叠多边形 all_water['geometry'] = all_water.geometry.make_valid() all_water = all_water.dissolve() # 合并为单一多边形,方便绘制
3. 改用边界框扩大查询范围
如果目标区域是岛屿或沿海地带,features_from_point的固定距离可能无法覆盖完整海域。建议先获取区域边界,再用边界框查询:
# 获取目标区域的地理边界(以圣多明各为例) gdf = ox.geocode_to_gdf("Santo Domingo, Dominican Republic") bbox = gdf.total_bounds # 格式:(minx, miny, maxx, maxy) # 通过边界框查询水体数据 water_gdf = ox.features_from_bbox( bbox[1], bbox[0], bbox[3], bbox[2], tags=water_tags )
4. 补充外部数据源(可选)
如果OSM数据在部分区域缺失,可结合Natural Earth的公开海域数据补充:
# 加载Natural Earth的低分辨率海域数据 ne_seas = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) ne_seas = ne_seas[ne_seas['featurecla'] == 'Ocean'] # 裁剪到目标区域 target_area = gdf.geometry.iloc[0] ne_seas_cropped = ne_seas.clip(target_area) # 合并OSM与Natural Earth数据 final_water = pd.concat([water_gdf, ne_seas_cropped], ignore_index=True).dissolve()
内容的提问来源于stack exchange,提问作者Jon
相关产品推荐
相关产品推荐

