1

我有一个由 4000 个特征(线)组成的区域网络的 shapefile。我想分割长度超过 500 米的线,以便为每条线获得 500 米的最大长度。例如,7公里的线路,需要切割14个部分,每个部分都必须保持与原件相同的属性。

我尝试使用cutShapely 的功能,但它不起作用,因为我需要在地理数据框中分离要素的几何形状以切割线。

4

1 回答 1

0

为了解决这个问题,我决定开发一个功能,根据件数将一条线切割成多行。

首先,我检查了 shapely 用户手册 ( https://shapely.readthedocs.io/en/latest/manual.html ) 中的“剪切”功能。此函数允许将线(LineString)分成两部分,以线和距离作为参数

 def cut(line, distance):
 # Cuts a line in two at a distance from its starting point
 if distance <= 0.0 or distance >= line.length:
      return [LineString(line)]
 coords = list(line.coords)
 for i, p in enumerate(coords):
      pd = line.project(Point(p))
      if pd == distance:
          return [
                  LineString(coords[:i+1]),
                  LineString(coords[i:])]
      if pd > distance:
          cp = line.interpolate(distance)
          return [
                   LineString(coords[:i] + [(cp.x, cp.y)]),
                   LineString([(cp.x, cp.y)] + coords[i:])]

然后,我使用此函数使用参数片段和线条多次剪切 LineString。Pieces 用于将线的长度分成相等的部分,以便切割线。

MultiCut 是用要切割的线和要从线获得的片数来定义的

def MultiCut(line, pieces):

#Firts we need to define two list to append the results (lines) and the lines to cut
lines_result = [] #All the lines are add to this list
lines_to_cut = [] #The lines to cut are add to this list

#We must ensure that pieces are higher than 2
if pieces == 1: #If pieces are 1 the result is the same line
    lines_result.append(line) 
elif pieces == 2: #If pieces are 2 the result is the line cut by the middle point
    distance = (line.length)/pieces
    lines_result.append(cut(line, distance)[0])
    lines_result.append(cut(line, distance)[1])
else: # If pieces is more than 3 we star to cut the line in the number of pieces
    # We use a loop  from the first to the penultimate piece 
    for i in range(1, pieces): 
        # The first piece is cut to save the result and the rest of the line
        if i == 1:
            distance = (line.length)/pieces #Distance is calculate as the lenght of the line divided by the number of pieces
            lines_result.append(cut(line, distance)[0]) #We cut the line and 
            save the first part in lines result
            lines_to_cut = cut(line, distance)[1] #We save the rest of the line in lines to cut in order to continue with the split

        #If pieces are equal to pieces minus two we can split the line and 
        #save only the first part in lines result in order to continue with 
        #the split
        if  1 < i <= pieces - 2:
            distance = (line.length)/pieces
            lines_result.append(cut(lines_to_cut, distance)[0])
            lines_to_cut = cut(lines_to_cut, distance)[1]

        #Finally if pieces are equal to pieces minus 1 we can cut the line 
        #and save both of the parts in lines result
        if (i != 1) and (i == pieces-1):
            distance = (line.length)/pieces
            lines_result.append(cut(lines_to_cut, distance)[0])
            lines_result.append(cut(lines_to_cut, distance)[1])

return lines_result 

最后,我们将线切割成您想要的件数。例如,如果您有一行 5 个单位:

 line = LineString([(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0)])

您可以使用距离分割线

cut(line, 2.5)

或者,您可以使用 MultiCut 将线分割成您需要的片数

MultiCut(line, 2) #Cut the line by middle
MultiCut(line, 5) #Cut the line in five parts with 1 as distance

因为我需要在多行中剪切一个 shapefile,所以我在一个循环中使用 MultiCut 来做到这一点。

import pandas as pd
import geopandas as gpd
import shapely.geometry as geom
import numpy as np
from shapely.geometry import LineString
from shapely.geometry import Point
from shapely.geometry import MultiLineString

#I read the shapefile with geopandas
df = gpd.read_file('Red_local_Samana.shp')
#I project the shapefile 
df = df.to_crs("EPSG:3115")
#I took the lines (LineString) of the geodataframe 
network_to_cut = df.geometry

results = []
for j in range(0, len(network_to_cut)):

    if network_to_cut[j].length > 500:

        line = network_to_cut[j]
        pieces = int(((line.length)//500)+1)
        results.append(list(MultiCut(line, pieces))) 

使用这种方法,我将 shapefile 中高于 500 米的所有线条分成至少 500 米的片段

于 2020-04-10T20:55:04.647 回答