In the example, you could just do the math and find the intersection between the lines generated by the segments (the MultiLineString last segment and the segment of the polygon boundary), without relaying on any shapely library computation.
(I don't understand why you are using a MultiLineString when you should be using a simple LineString, since all line segments are consecutive).
A little more general solution would be the following:
from shapely.geometry import *
def getExtrapoledLine(p1,p2):
'Creates a line extrapoled in p1->p2 direction'
EXTRAPOL_RATIO = 10
a = p1
b = (p1[0]+EXTRAPOL_RATIO*(p2[0]-p1[0]), p1[1]+EXTRAPOL_RATIO*(p2[1]-p1[1]) )
return LineString([a,b])
line=LineString([(3,0),(3,5),(7,9.5)])
box=Polygon([(0,0),(0,10),(10,10),(10,0)])
box_ext = LinearRing(box.exterior.coords) #we only care about the boundary intersection
l_coords = list(line.coords)
long_line = getExtrapoledLine(*l_coords[-2:]) #we use the last two points
if box_ext.intersects(long_line):
intersection_points = box_ext.intersection(long_line)
new_point_coords = list(intersection_points.coords)[0] #
else:
raise Exception("Something went really wrong")
l_coords.append(new_point_coords)
new_extended_line = LineString(l_coords)
# To see the problem:
import pylab
x, y = box.exterior.xy
pylab.plot(x,y)
l_coords = list(line.coords)
x = [p[0] for p in l_coords]
y = [p[1] for p in l_coords]
pylab.plot(x,y)
longl_coords = list(long_line.coords)
x = [p[0] for p in longl_coords]
y = [p[1] for p in longl_coords]
pylab.plot(x,y)
pylab.plot(new_point_coords[0], new_point_coords[1], 'o')
pylab.show()
# To see the solution:
x, y = box.exterior.xy
pylab.plot(x,y)
l_coords = list(new_extended_line.coords)
x = [p[0] for p in l_coords]
y = [p[1] for p in l_coords]
pylab.plot(x,y)
pylab.show()
In this solution, we extrapolate the last segment of the Line and intersect it with the boundary line of the polygon to get the intersection point.
A few remarks:
- Notice the EXTRAPOL_RATIO constant. Depending on the polygon complexity or dimensions, it could make the line to intersect the polygon boundary in more than one point, or in not point at all.
- You depend on knowing that it is the last segment of the line you want to extend.
I think that there are a lot of solution to this problem. Depending on how general is the solution you want, it can turn very complicated. I imagine you can adapt the code to more general settings.