如何用Python将LineString转为带2英里缓冲区的Polygon?
错误分析与修正方案
核心错误点
gpd.points_from_xy参数错误:该函数需要分别传入x坐标序列和y坐标序列,你写成了gpd.points_from_xy([(x,y)]),缺少了y参数。其实单个点用shapely.geometry.Point更简单,没必要用GeoPandas的points_from_xy。- 变量名冲突:循环遍历Feature时用了
f作为变量名,后续写文件时又用f作为文件句柄,会覆盖之前的变量。 - 缓冲区单位错误:原数据是WGS84(EPSG:4326,经纬度坐标系),直接调用
buffer(2)得到的是2度范围,不是2英里。需要先转换到支持英里/米单位的投影坐标系,缓冲后再转回WGS84。 - MultiPolygon构造错误:你传入
MultiPolygon的是GeoSeries对象,而它需要的是单个shapely Polygon对象的列表。 - JSON导出错误:最后写文件时用了
dump但未导入json.dump,缺少json.前缀。
修正后的代码
import json import geopandas as gpd from shapely.geometry import MultiPolygon, Point from geopandas import GeoSeries # 加载GeoJSON with open('Sample_lines.geojson') as file: gj = json.load(file) features = [] for feat in gj['features']: coords = feat['geometry']['coordinates'] buffers = [] # 遍历每个坐标点,忽略z值 for x, y, z in coords: # 创建单个点几何对象 point = Point(x, y) # 转换为GeoSeries并切换到支持英里的投影(示例用UTM 12N,EPSG:26912,适配数据区域) point_gs = GeoSeries([point], crs="EPSG:4326").to_crs("EPSG:26912") # 2英里转换为米(1英里≈1609.34米) buffer_poly = point_gs.buffer(2 * 1609.34).to_crs("EPSG:4326").iloc[0] buffers.append(buffer_poly) # 创建MultiPolygon mpolygon = MultiPolygon(buffers) # 构造新Feature features.append({ 'type': 'Feature', 'geometry': mpolygon.__geo_interface__, 'properties': feat['properties'] }) # 构造新的FeatureCollection new_gj = { "type": "FeatureCollection", "crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:OGC:1.3:CRS84"}}, "features": features } # 导出为GeoJSON with open('lines2Polygon.geojson', 'w') as output_file: json.dump(new_gj, output_file, indent=2) print("转换完成,已保存为lines2Polygon.geojson")
关键修正说明
- 点对象创建:用
shapely.geometry.Point(x, y)直接创建单个点,比points_from_xy更适合单个点的场景。 - 投影转换:将点转换为UTM投影(EPSG:26912,适配你数据中的美国犹他州区域),把2英里转换为米(1英里≈1609.34米)进行缓冲,确保单位正确,之后再转回WGS84坐标系。
- 变量名调整:把遍历Feature的变量从
f改成feat,避免和文件句柄冲突。 - MultiPolygon构造:从缓冲后的GeoSeries中提取单个Polygon对象(
iloc[0]),确保传入的是shapely几何对象列表。 - JSON导出:使用
json.dump正确序列化GeoJSON对象,并添加缩进让输出更易读。
内容的提问来源于stack exchange,提问作者Tarak Pandya
相关产品推荐
相关产品推荐

