2

I have a shapely LineString and defined a shapely Point which lies along the LineString.

How can I find the vertices of the LineString which lie either side of the point? (split the line in two).

This is very similar to this blog post by the author: http://sgillies.net/blog/1040/shapely-recipes/

Except, instead of cutting by distance along the line, I want to cut given a point that lies along the line.

  • one way is (if shapely supports) linear referencing. this toblerity.org/shapely/manual.html manual gives me impression that it supports it. – simplexio Jan 28 '14 at 14:23
  • linear referencing refers to a group of methods (at least when referring to shapely). Which method are you referring to? There are only two given in the manual, interpolate and project, which could be helpful but don't actually solve the problem – James Jan 28 '14 at 14:36
  • i dont know shapely, but in postgis procedure goes like this. locate closest point on line, interpolate length from start at given point , cut line at that point. In code : SELECT ST_LineSubstring(line_geom,0,ST_LineLocatePoint(line_geom, point_geom)) FROM xxx.. would return you part of line which is before point – simplexio Jan 29 '14 at 10:06
8

I don't understand your question:

line = LineString([(0, 0), (2, 2)])
# create a point which lies along the line
point = line.interpolate(1)
line.contains(point)
True

enter image description here

You want the two lines which lie either side of the point ?

line1 = LineString([line.coords[0],(point.x, point.y)])
line2 = LineString([(point.x, point.y), line.coords[1]])

enter image description here

Upgrade 1: with a line with multiple vertices

enter image description here

You need to iterate through the segments of the LineString to find the one that contains the point

The LineString must be iterate as pair to divide the line in segments.

def pairs(lst):
    for i in range(1, len(lst)):
        yield lst[i-1], lst[i]

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

 for pair in pairs(list(line.coords)):
      if LineString([pair[0],pair[1]]).contains(point):
          print LineString([pair[0],pair[1]])

LINESTRING (2.00 2.00, 2.00 3.00)

And you can use the previous answer: a rapid solution, for example ( this can be done better):

line1 = []
line2 = []
cp = False
for pair in pairs(list(line.coords)):
    if cp == False:
       line1.append(pair[0])
    if cp == True:
       line2.append(pair[1])
    if LineString([pair[0],pair[1]]).contains(point):
       line1.append((point.x,point.y))
       line2.append((point.x,point.y))
       line2.append(pair[1])
       cp = True
line1 = LineString(line1)
line2 = LineString(line2)

Result:

enter image description here

  • You have given an oversimplified version, which you have solved by visually inspecting the coordinates. Assume that the original linestring you created has any number of points. Let's keep it to 3 for simplicity. You create a point at some distance using interpolation. Now, how to get all the vertices of the original linestring either side of that point as seperate linestrings? – James Jan 28 '14 at 14:32
  • I adapt the solution – gene Jan 28 '14 at 14:37
  • Your edit still doesnt answer the question, as you have still retrieved the indices of the vertices either side of the point by visually inspecting. I have a linestring with multiple vertices and a point at an arbritary distance along the linestring: I don't know between which vertices this point lies – James Jan 28 '14 at 14:39
  • look at the Shapely User Manual, there is an example of cutting a line at a specified distance. – gene Jan 28 '14 at 14:45
  • See my above post, which mentions using that method. However, I want to cut the line given a coordinate along the line, not a specified distance. You could back track to get the distance from the coordinate to the starting point and then employ that method, but it seems pretty inefficient – James Jan 28 '14 at 14:47
0

The best answer I can come up with so far is to use the 'cut' method outlined here:

http://toblerity.org/shapely/manual.html#linear-referencing-methods

But first calculate the distance between the arbitary point and the start of the line. This would have to be the distance along the line.. so it all seems a bit long winded. I'm sure there must be a simpler way...

Edit: I misinterpreted the project method thinking it would return the distance to the nearest point on the LineString; it seems like it returns the distance to the start. So, using the cut method as above is slightly less clunky than I thought

  • 1
    I was working on the same thing a bit ago and used "project" to modify Sean's example, which worked well. – amcaninch Jan 29 '14 at 20:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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