pythonpostgisgeopandasshapely

How to split a LineString to segments


My data set consists of a LineString and I want to filter out the individual line segments of this LineString. More precisely, every single street segment.

Until now I have extracted the individual points from the data set and saved them in a separate list. Furthermore, I would like to collect these points again and create individual LineStrings from them to store them into a Geodataframe. The data has this form:

LINESTRING (3275.284016199762 340555.8579582386, 3241.504528076811 340504.1348617533, 3245.415803206172 340501.457084205, 3280.414559049542 340552.7138220053, 3285.19053022

My problem with this is that I would have to create and explicitly save a separate LineString for each iteration. Can anyone help me with this? Is there a better method for this?

from shapely.geometry import Point, LineString

#Loop over LineString and gather Points
c=[]

for i in range(0,end):
    c.append(Point(route1.coords[i]))


iterator=len(c)
max=len(c)-1

#Loop to store LineStrings - got stuck here
for i in np.arange(0,iterator):
    if i<max:
        LineString([c[i], c[i+1]]).wkt

    else:
        break;

The output should look like this:

Linestring(Point A, Point B)  
Linestring(Point B, Point C)  
Linestring(Point C, Point D)  
...  
Linestring(Point Y, Point Z)

Solution

  • Speaking of Shapely, it doesn't provide a function to split a curve object (LineString or LinearRing) to segments, so you have to write your own. Here is an example of how you could do it using zip to iterate over pairs of coordinates and map them to LineString's:

    from shapely.geometry import LineString, LinearRing
    
    
    def segments(curve):
        return list(map(LineString, zip(curve.coords[:-1], curve.coords[1:])))
    
    
    line = LineString([(0, 0), (1, 1), (2, 2)])
    ring = LinearRing([(0, 0), (1, 0), (1, 1), (0, 1)])
    
    line_segments = segments(line)
    for segment in line_segments:
        print(segment)
    # LINESTRING (0 0, 1 1)
    # LINESTRING (1 1, 2 2)
    
    ring_segments = segments(ring)
    for segment in ring_segments:
        print(segment)
    # LINESTRING (0 0, 1 0)
    # LINESTRING (1 0, 1 1)
    # LINESTRING (1 1, 0 1)
    # LINESTRING (0 1, 0 0)