Как уплотнить вершины LineString в Shapely / GeoPandas

Sep 01 2020

Я ищу аналог инструмента уплотнения в ArcGIS, но с GeoPandas или Shapely. У меня есть линия, которую хотелось бы уплотнить на определенном расстоянии; как добавить вершины линии с помощью Python?


Предположим, у меня есть линия с двумя вершинами (WKT) LINESTRING (0 0, 9 0). как мне разделить линию на равное расстояние 1, чтобы она возвращала ту же строку, но вместо 2 вершин у нее было 10 вершин? В результате я ожидаю:
LINESTRING (0 0, 1 0, 2 0, 3 0, 4 0, 5 0, 6 0, 7 0, 8 0, 9 0). Я нашел этот пост, который похож на то, что я хочу, но в нем используется ArcGIS вместо GeoPandas и Shapely.

Ответы

1 NickPucino Sep 05 2020 at 07:35

Я создал для вас функцию. Вот ваша строка, которую я называю old_line:

old_line=LineString([(0,0), (9,0)]) # your line with 2 vertices

Вот функция, которая принимает линейную геометрию в качестве основного ввода, вы назначаете шаг (т.е. интервал вдоль старой линии) и дополнительную систему координат (crs) для привязки новой уплотненной линии.

   def densify_geometry (line_geometry, step, crs=None):
        
        # crs: epsg code of a coordinate reference system you want your line to be georeferenced with
        # step: add a vertice every step in whatever unit your coordinate reference system use.
    
        length_m=line_geometry.length # get the length
    
        xy=[] # to store new tuples of coordinates
    
        for distance_along_old_line in np.arange(0,int(length_m),step): 
    
            point = line_geometry.interpolate(distance_along_old_line) # interpolate a point every step along the old line
            xp,yp = point.x, point.y # extract the coordinates
    
            xy.append((xp,yp)) # and store them in xy list
    
        new_line=LineString(xy) # Here, we finally create a new line with densified points.
        
        if crs != None:  #  If you want to georeference your new geometry, uses crs to do the job.
            new_line_geo=gpd.geoseries.GeoSeries(new_line,crs=crs) 
            return new_line_geo
    
        else:
            return new_line

Теперь бегаем:

densify_geometry(line_geometry=old_line, step= 0.5, crs= 32754)

возвращает:

LINESTRING (0.00000 0.00000, 0.50000 0.00000, ...
dtype: geometry

Если вы хотите применить его ко всемуGeoDataFrame столбцу геометрии :

kwargs_dict={'step':0.5,
             'crs':32754}

your_gdf["new_geometry"]=your_gdf.geometry.apply(densify_geometry, kwargs=**kwargs_dict)

Это должно сработать.