Splitting line on intersection to another line using Shapely

I'm finding a solution for split a `LineString` on intersection to another `LineString`. My first solution is:

``````from shapely import wkt
from shapely.ops import split

first_line = wkt.loads('LINESTRING (28.112115297354478 57.00625960468798, 8.219782679723316 20.076477637253483)')
second_line = wkt.loads('LINESTRING (-36.57919844025919 19.94938832911169, 8.426621630216765 20.077064414418004, 29.684689833718174 0.223433149286052)')

real_intersection = second_line.intersection(first_line) # POINT (8.219782679723316 20.076477637253483)
split_second_line = split(second_line, real_intersection)
``````

Based on split()' documentation I expect to see at least two `LINESTRING` into `GEOMETRYCOLLECTION`. The output: `GEOMETRYCOLLECTION (LINESTRING (-36.57919844025919 19.94938832911169, 8.426621630216765 20.077064414418004, 29.684689833718174 0.223433149286052))`

Apparently there aren't intersection between `first_line` and `second_line` so I build an extension of `first_line`:

``````from math import atan2, cos, sin, degrees
from shapely.geometry import Point, LineString

first_line_coords = list(first_line.coords)
lon1 = first_line_coords[0][0]
lat1 = first_line_coords[0][1]
lon2 = first_line_coords[1][0]
lat2 = first_line_coords[1][1]

angle = atan2(cos(lat1)*sin(lat2)-sin(lat1) * cos(lat2)*cos(lon2-lon1), sin(lon2-lon1)*cos(lat2))
bearing = (degrees(angle) + 360) % 360

new_first_line_length = first_line.length + 10
end_point = Point(lon1 + new_first_line_length * math.cos(bearing), lon1 + new_first_line_length * math.sin(bearing))
start_point = Point(first_line_coords[0])
new_first_line = LineString([start_point, end_point])

new_real_intersection = second_line.intersection(new_first_line) # POINT (7.015156377654302 20.073060257673145)
new_split_second_line = split(second_line, new_real_intersection)
``````

The output is: `GEOMETRYCOLLECTION (LINESTRING (-36.57919844025919 19.94938832911169, 8.426621630216765 20.077064414418004, 29.684689833718174 0.223433149286052))`

Again I have only one `LINESTRING`. I don't understand where is my mistake.

• Why don't you split a line with the second line directly? Points that are computed by functions like your new_real_intersection tends to be not exact because of inaccuracies in computing with floating point numbers. It is quite possible that for the split function the point does not intersect the line. Commented Mar 23, 2022 at 11:09

The intersection is a point and there are floating point precision errors when finding a point on a line (Determine if Shapely point is within a LineString/MultiLineString)

``````real_intersection = second_line.intersection(first_line) # red point
``````

``````# this point is on both lines
first_line.distance(real_intersection) < 1e-8
True
second_line.distance(real_intersection) < 1e-8
True
from shapely.ops import unary_union
uu = unary_union([first_line,second_line])
for line in uu:
print(line)
LINESTRING (28.11211529735448 57.00625960468798, 8.219782679723316 20.07647763725348)
LINESTRING (-36.57919844025919 19.94938832911169, 8.219782679723316 20.07647763725348)
LINESTRING (8.219782679723316 20.07647763725348, 8.426621630216765 20.077064414418, 29.68468983371817 0.223433149286052)
``````

• Thank you @gene ! I did not know `unary_union` Commented Mar 23, 2022 at 13:04
• Another pair of lines doesn't return a right output. I think it depends on fact that the distance between intersection point and a vertex is very little, 0.11 meters. Probably `unary_union` has a sort of tollerance. The lines: `first_line = wkt.loads('LINESTRING (-57.64575251580113 -28.120657788715818, -58.3010518547059 -8.170824371956757)') second_line = wkt.loads('LINESTRING (-38.74969189046654 -2.4577646421465573, -58.411809027639016 -8.20318848093072)')` Commented Mar 23, 2022 at 13:39
• Normal, there is no intersection between the two lines
– gene
Commented Mar 23, 2022 at 13:52
• I have `True` on both of `*.distance(real_intersection) < 1e-8` for lines of my last comment Commented Mar 23, 2022 at 13:56
• `unary_union`uses the true intersection (as in your first example) and not the control by distance
– gene
Commented Mar 23, 2022 at 14:17