16

I'm trying to split a shapefile of geometry type 'line' at a shapefile of geometry type 'point. These points are snapped to the lines and are the start points/end points of other line shapefiles.

Something like this : The points are snapped to the black lines.

splitAtPoints

As of now I'm working with Geopandas/Shapely/Fiona. I've searched for a native function in Shapely that performs the split; however, I've had no luck in finding a solution. This is also true when searching through Shapely's official docs. This is odd since the split is among the basic geoprocessing tools.

My goal is to give a function of the two shapefiles (lines & points) and split the lines at points (like ArcGIS' tool). The split lines should then be stored in a different shapefile. This seems easy to do but the lack of documentation is a bump in the road.

Any ideas on how I can do this in python using Geopandas/Shapely?

PolyGeo
65.5k29 gold badges115 silver badges350 bronze badges
asked Jul 21, 2016 at 15:31

1 Answer 1

19

You have many solutions and I use here a simple example

1) the easiest way

from shapely.geometry import Point, LineString
line = LineString([(1,2),(2,4),(4,5)])
point = Point(2,4)

First, you must determine if the point is within the line (Determine if shapely point is within a linestring/multilinestring)

line.distance(point) < 1e-8
True
print LineString([line.coords[0],point.coords[:][0]])
LINESTRING (1 2, 2 4)
print LineString([point.coords[:][0], line.coords[-1]])
LINESTRING (2 4, 4 5)

2) with the shapely function split

from shapely.ops import split
result = split(line, point)
result.wkt
'GEOMETRYCOLLECTION (LINESTRING (1 2, 2 4), LINESTRING (2 4, 4 5))'

3) from Get the vertices on a LineString either side of a Point

from shapely.geometry import Point,LineString 
def split(line_string, point):
 coords = line_string.coords
 j = None 
 for i in range(len(coords) - 1):
 if LineString(coords[i:i + 2]).intersects(point):
 j = i
 break 
 assert j is not None 
 # Make sure to always include the point in the first group
 if Point(coords[j + 1:j + 2]).equals(point):
 return coords[:j + 2], coords[j + 1:]
 else:
 return coords[:j + 1], coords[j:]
line1,line2 = split(line,point)
line1 = LineString(line1)
line2 = LineString(line2)
print line1, line2
LINESTRING (1 2, 2 4) LINESTRING (2 4, 4 5)

4) from Shapely Split LineStrings at Intersections with other LineStrings

# First coords of line (start + end)
coords = [line.coords[0], line.coords[-1]] 
# Add the coords from the points
coords += point.coords
# Calculate the distance along the line for each point
dists = [line.project(Point(p)) for p in coords]
# sort the coordinates
coords = [p for (d, p) in sorted(zip(dists, coords))]
lines = [LineString([coords[i], coords[i+1]]) for i in range(len(coords)-1)]
for lin in lines:
 print lin
LINESTRING (1 2, 2 4)
LINESTRING (2 4, 4 5)

5) you can also examine and adapt

answered Jul 21, 2016 at 17:25
11
  • Thank you @gene for your detailed answer! At first I was looking for a native function in Shapely that does that. Commented Jul 22, 2016 at 7:53
  • The function split Commented Jul 22, 2016 at 10:02
  • The split function in Shapely is not recognized apparently. I tried importing : from shapely.ops import split But I get an unresolved error. I install the split package and nothing happens still. Very odd. I already have the points and lines in shapefiles so all I need to do is the split. The point are already projected on the lines. Commented Jul 22, 2016 at 20:20
  • look at the github version of shapely ops.py line 329 Commented Jul 22, 2016 at 20:58
  • 1
    The split function could be nice, but no matter how I try to snap the point onto the line, it won't split the line at that point. Commented Dec 22, 2022 at 13:04

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.