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

如何将overpy获取的OSM数据转为含多边形的GeoDataFrame

问题原因

OSM中行政边界是以relation类型存储的,其几何成员是构成边界的零散未闭合LineString。直接调用Overpass的geom()方法只会返回所有线成员的集合,不会自动执行环闭合、面组装逻辑,因此直接转换得到的GeoDataFrame中只会存在包含LineString的GeometryCollection,没有可用的Polygon/MultiPolygon类型几何。

解决方案

不需要调整Overpass查询逻辑,在拿到返回结果后,通过shapely完成线段拼接、面组装即可得到符合要求的GeoDataFrame,完整可运行代码如下:

import requests
import geopandas as gpd
from shapely.geometry import shape, MultiPolygon
from shapely.ops import linemerge, polygonize

url = "https://maps.mail.ru/osm/tools/overpass/api/interpreter"
query = """[out:json];
area['boundary' = 'administrative']['name' = 'Москва'] -> .MSK;
(
relation(area.MSK)['admin_level' = 8]['boundary' = 'administrative']['name'='Бескудниковский район';
relation(area.MSK)['admin_level' = 8]['boundary' = 'administrative']['name'='район Восточное Дегунино';
);
convert item ::=::,::geom=geom(),_osm_type=type();
out geom;"""
response = requests.get(url, params={'data': query})
data = response.json()

processed_records = []
for elem in data["elements"]:
    # 提取区域name属性
    record = {"name": elem["tags"].get("name", "unnamed_area")}
    # 读取返回的原始几何集合,拼接零散边界线段
    raw_geom = shape(elem["geometry"])
    merged_boundary = linemerge(raw_geom)
    # 从闭合边界提取所有面
    area_polygons = list(polygonize(merged_boundary))
    # 组装为对应几何类型
    record["geometry"] = area_polygons[0] if len(area_polygons) == 1 else MultiPolygon(area_polygons)
    processed_records.append(record)

# 构建最终GeoDataFrame,指定OSM使用的WGS84坐标系
geo_df = gpd.GeoDataFrame(processed_records, crs="EPSG:4326")

运行后得到的geo_df从0开始索引,每行对应一个行政区,name列存区域名称,geometry列为带坐标的Polygon/MultiPolygon类型,可直接用于可视化。

注意事项
  • 上述逻辑会自动识别边界中的闭合环,自动处理带飞地、内部孔洞的行政区几何
  • 如果遇到个别边界线段端点存在微小间隙无法拼接,可以给linemerge传入容差参数,例如linemerge(raw_geom, tolerance=1e-7),会自动拼接距离小于容差的线段端点
  • 可通过执行print(geo_df.geom_type)验证几何类型,输出结果不会再出现LineString或GeometryCollection类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:06:09