I have a line dataset that contains some lines where the "end points" are actually found in the middle of the line. In the image below, the nodes are shown in green and one of the end points in red. The line doubles back on itself.

How would I ensure the end points are actually at the end of the line, and remove the overlap?

complex line

These lines are both valid, and complex - as they have overlaps, as confirmed using Shapely.

>>> from shapely.wkt import loads
>>> wkt = "LINESTRING (0 0, 2 0, 1 0)"
>>> l = loads(wkt)
>>> l.is_valid
>>> l.is_simple

Ordering the coordinates would work in some cases:

>>> sorted(l.coords)
[(0.0, 0.0), (1.0, 0.0), (2.0, 0.0)]

But not in others as it would change the geometry of the line:

>>> wkt = "LINESTRING (0 0, 2 0, 1 -1)"
>>> l = loads(wkt)
>>> sorted(l.coords)
[(0.0, 0.0), (1.0, -1.0), (2.0, 0.0)]

Attempts at buffering the line with a 0 buffer, and merging lines have not changed the coordinate order.

1 Answer 1


You can re-node the non-simple LineString with one or two steps:

  1. Create an intersection of the object with itself, which may create a MultiLineString
  2. To try and make a singular LineString, use linemerge

For example:

from shapely.wkt import loads as load_wkt
from shapely.ops import linemerge

# Input LineString: valid, but non-simple
ls = load_wkt('LINESTRING(0 0, 2 0, 1 0)')
assert ls.is_valid and not ls.is_simple

# Make a simple shape, by finding the intersection with itself
sls = ls.intersection(ls)
assert sls.is_valid and sls.is_simple

# If it was a LineString to start with, then attempt to put it back to that type
if ls.geom_type == 'LineString' and sls.geom_type == 'MultiLineString':
    fls = linemerge(sls)
    fls = sls

assert fls.is_valid and fls.is_simple

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.