【问题标题】:Calculate length of all segments in polygon using geopandas使用 geopandas 计算多边形中所有线段的长度
【发布时间】:2021-08-27 08:58:45
【问题描述】:

我想解决这个小问题,我到处寻找答案。我找不到它似乎很奇怪,但它可能只是我。

所以,我有这个数据框

df= 
id     x_zone     y_zone
0  A1  65.422080  48.147850
1  A1  46.635708  51.165745
2  A1  46.597984  47.657444
3  A1  68.477700  44.073700
4  A3  46.635708  54.108190
5  A3  46.635708  51.844770
6  A3  63.309560  48.826878
7  A3  62.215572  54.108190

我将其转换为 geopandas 数据框:

df_geometry = gpd.GeoDataFrame(geometry=df.groupby('id').apply(
    lambda g: Polygon(gpd.points_from_xy(g['x_zone'], g['y_zone']))))
df_geometry = df_geometry.reset_index()
print(df_geometry)

返回:

                                             
id                                        geometry                                 
A1  POLYGON ((65.42208 48.14785, 46.63571 51.16575...
A3  POLYGON ((46.63571 54.10819, 46.63571 51.84477...

我可以计算面积和周长:

df_geometry["area"] = df_geometry['geometry'].area
df_geometry["perimeter"] = df_geometry['geometry'].length

给出:

id                                           geometry       area  perimeter
0  A1  POLYGON ((65.42208 48.14785, 46.63571 51.16575...  72.106390  49.799695
1  A3  POLYGON ((46.63571 54.10819, 46.63571 51.84477...  60.011026  40.181476

现在,我的问题的核心是:如果可以计算长度,则肯定正在计算多边形的每一段的长度。我怎样才能找回这个?

我知道对于非常复杂的多边形(例如国家地图,这可能是存储问题)。有人有想法吗?

【问题讨论】:

  • 不是segment length = abs(pt[x] - pt[x-1]) where x = 0 to len(Polygon Points) -1 ?
  • 其实你需要使用df_geometry.geometry.exterior[0].xy[0]获取所有x坐标和df_geometry.geometry.exterior[0].xy[1]然后计算长度.
  • 您使用的是lat, long 坐标吗?您希望您的细分受众群使用哪种length
  • 我只需要欧几里得距离。我正在查看的是 100 * 100 米,x、y 是相对于平面中的固定点,而不是经纬度坐标。 sum_of_squares =np.square(np.subtract(df_geometry.geometry.exterior[0].xy[0],df_geometry.geometry.exterior[0].xy[1])), lengths = np.sqrt(sum_of_squares) 是一个答案,但我希望有更优雅的东西。

标签: python-3.x pandas geopandas


【解决方案1】:

这是可运行的代码,显示了创建包含所需段长度的数据帧的所有步骤。

from io import StringIO
import geopandas as gpd
import pandas as pd
from shapely.geometry import Point, Polygon
import numpy as np

dats_str = """index  id   x_zone  y_zone
0  A1  65.422080  48.147850
1  A1  46.635708  51.165745
2  A1  46.597984  47.657444
3  A1  68.477700  44.073700
4  A3  46.635708  54.108190
5  A3  46.635708  51.844770
6  A3  63.309560  48.826878
7  A3  62.215572  54.108190"""
# read the string, convert to dataframe
df1 = pd.read_csv(StringIO(dats_str), sep='\s+', index_col='index') #good for space/s separation
gdf = gpd.GeoDataFrame(geometry=df1.groupby('id')
                .apply(lambda g: Polygon(gpd.points_from_xy(g['x_zone'], g['y_zone']))))
gdf = gdf.reset_index() #bring `id` to `column` status

# Facts about polygon outer vertices
# - first vertex is the same as the last
# - to get segments, ignore zero-th point (use it as from_point in next row)
# create basic lists for creation of new dataframe
indx = []  # for A1, A3
sequ = []  # for seg order
pxy0 = []  # from-point
pxy1 = []  # to-point
for ix,geom in zip(gdf.id, gdf.geometry):
    num_pts = len(geom.exterior.xy[0])
    #print(ix, "Num points:", num_pts)
    old_xy = []
    for inx, (x,y) in enumerate(zip(geom.exterior.xy[0],geom.exterior.xy[1])):
        if (inx==0):
            # first vertex is the same as the last
            pass
        else:
            indx.append(ix)
            sequ.append(inx)
            pxy0.append(Point(old_xy))
            pxy1.append(Point(x,y))
        old_xy = (x,y)

# Create new geodataframe 
pgon_segs  = gpd.GeoDataFrame({"poly_id": indx,
                 "vertex_id": sequ,
                 "fr_point": pxy0,
                 "to_point": pxy1}, geometry="to_point")
# Compute segment lengths
# Note: seg length is Euclidean distance, ***not geographic***
pgon_segs["seg_length"] = pgon_segs.apply(lambda row: row.fr_point.distance(row.to_point), axis=1)

pgon_segs的内容:

 poly_id  vertex_id  fr_point   to_point     seg_length
0   A1  1   POINT (65.42207999999999 48.14785)  POINT (46.63571 51.16575)   19.027230
1   A1  2   POINT (46.635708 51.165745) POINT (46.59798 47.65744)   3.508504
2   A1  3   POINT (46.597984 47.657444) POINT (68.47770 44.07370)   22.171270
3   A1  4   POINT (68.4777 44.0737) POINT (65.42208 48.14785)   5.092692
4   A3  1   POINT (46.635708 54.10819)  POINT (46.63571 51.84477)   2.263420
5   A3  2   POINT (46.635708 51.84477)  POINT (63.30956 48.82688)   16.944764
6   A3  3   POINT (63.30956 48.826878)  POINT (62.21557 54.10819)   5.393428
7   A3  4   POINT (62.215572 54.10819)  POINT (46.63571 54.10819)   15.579864

【讨论】:

  • 这太棒了!它超出了我的预期,输出可能是我下一步的一个步骤......问题是我想将所有多边形分成相等的部分,即面积相等的部分。它们都是“矩形”或接近矩形。我知道 qgis 有一个名为 PolygonDivider 的模块,但我很难使用它。非常感谢!
  • 我会添加 pgon_segs= pgon_segs.set_geometry("fr_point") 以确保这些点也是几何图形。再次,干得好。
猜你喜欢
  • 2012-08-25
  • 1970-01-01
  • 1970-01-01
  • 2019-12-17
  • 2019-05-14
  • 2023-01-26
  • 2021-03-21
  • 2021-01-02
  • 2018-01-02
相关资源
最近更新 更多