Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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.

share|improve this question
up vote 3 down vote accepted

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
share|improve this answer
Perfect! Thanks Mike – geographika Dec 18 '12 at 8:21

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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