Reputation: 330
I've created complex linestring as follows:
from shapely.geometry import LineString
complex_line = LineString([(-1, -1), (1, 1), (1, 0), (-1, 0)])
The line is valid but it is not simple. How can I get the crossing point (here [0,0])?
Upvotes: 1
Views: 1646
Reputation: 68146
You want to split the line at some point after the self-intersection. Then you can do isect_pnt = first.intersection(second)
. The trick is finding that point after the self-intersection.
So I'm going to loop through "split fractions" from 0.1 to 0.9 and split the geometry at each fraction of the total length and see if shapely can find a valid intersection. If it can, we can break out of the loop and stop searching. For splits that are before the self-intersection, isect_pnt = first.intersects(second)
will return False
and we can can keep searching.
One nuance here is that I'm going to use the interpolate
method to create the new geometries at a finer resolution
import numpy
from shapely.geometry import LineString, Point
complex_line = LineString([(-1, -1), (1, 1), (1, 0), (-1, 0)])
# initial, non-result
intersection = None
# fraction of total distance at which we'll split the line
for split in numpy.arange(0.1, 1, 0.1):
full_len = complex_line.length
split_len = full_len * split
# endpoint = False to make sure we don't get a false-positive
# at the split point
first = LineString([
complex_line.interpolate(d)
for d in numpy.linspace(0, split_len, num=25, endpoint=False)
])
second = LineString([
complex_line.interpolate(d)
for d in numpy.linspace(split_len, full_len, num=25)
])
if first.intersects(second):
intersection = first.intersection(second)
break
print(intersection)
And on my machine, that outputs:
POINT (0 0)
This is not very well optimized. On large, complex geometries, I can imagine that this could require more resolved interpolations of each half of the line end up pretty slow .
Upvotes: 2