如何将GEOS MultiLineString转换为Polygon?

13 投票
3 回答
24842 浏览
提问于 2025-04-15 23:30

我正在开发一个GeoDjango应用,用户可以上传地图文件,并进行一些基本的地图操作,比如查询多边形内的特征。

我发现用户有时会上传“多线字符串”(MultiLineString),而不是“多边形”(Polygon)。这会导致一些查询失败,因为这些查询是期待封闭的几何形状。

在Python中,如何将一个多线字符串对象转换成多边形,最好的方法是什么呢?

3 个回答

2

这段小代码可以节省很多时间,也许以后在geopandas中会加入更简洁的写法。

import geopandas as gpd
from shapely.geometry import Polygon, mapping

def linestring_to_polygon(fili_shps):
    gdf = gpd.read_file(fili_shps) #LINESTRING
    geom = [x for x in gdf.geometry]
    all_coords = mapping(geom[0])['coordinates']
    lats = [x[1] for x in all_coords]
    lons = [x[0] for x in all_coords]
    polyg = Polygon(zip(lons, lats))
    return gpd.GeoDataFrame(index=[0], crs=gdf.crs, geometry=[polyg])
4

这是对Carlos回答的一个修改,内容更简单,而且不仅返回一个元素,而是返回源文件中的所有行。

import geopandas as gpd
from shapely.geometry import Polygon, mapping

def linestring_to_polygon(fili_shps):
    gdf = gpd.read_file(fili_shps) #LINESTRING
    gdf['geometry'] = [Polygon(mapping(x)['coordinates']) for x in gdf.geometry]
    return gdf
15

嘿嘿,最开始我写的是这个:

def close_geometry(self, geometry):
   if geometry.empty or geometry[0].empty:
       return geometry # empty

   if(geometry[-1][-1] == geometry[0][0]):
       return geometry  # already closed

   result = None
   for linestring in geom:
      if result is None:
          resultstring = linestring.clone()
      else:
          resultstring.extend(linestring.coords)

   geom = Polygon(resultstring)

   return geom

但后来我发现有一个很方便的方法叫做 convex_hull,它可以自动帮你把多边形转换好。

>>> s1 = LineString((0, 0), (1, 1), (1, 2), (0, 1))
>>> s1.convex_hull
<Polygon object at ...>
>>> s1.convex_hull.coords
(((0.0, 0.0), (0.0, 1.0), (1.0, 2.0), (1.0, 1.0), (0.0, 0.0)),)

>>> m1=MultiLineString(s1)
>>> m1.convex_hull
<Polygon object at...>
>>> m1.convex_hull.coords
(((0.0, 0.0), (0.0, 1.0), (1.0, 2.0), (1.0, 1.0), (0.0, 0.0)),)

撰写回答