I have written a Python script that parses the coordinates out of a GPX file. The coordinates are stored as a list of tuples: (float lat, float long)
. I used Shapely's LineString
function to create a curve that I can work with for each GPX file.
After parsing through several GPX files, I had some intersecting curves and I wanted to calculate some information based on these intersecting curves. To keep it simple, imagine I have 3 lines (call them line1, line2, line3
). In this particular scenario, line1
intersects both line2
and line3
but line2
and line3
do not intersect. Or more visually:
|
|
--*--- Line 2 ------
|
|
|
Line 1
|
|
|
--*--- Line 3 ------
|
|
What I am trying to do is create a new curve from these existing curves. The start and end points of this curve would be the intersecting points (denoted by *
in the visual representation), and the middles points of the curve would be the points of line1
that fall between these intersecting points.
I have no problem getting the intersecting points using Shapely's intersection()
method, but I have no idea how to grab the points of line1
that fall between these intersecting points.
I thought about determining if line1
runs east/west or north/south. Based on that result I could compare the latitude or longitude of the intersecting points against every point in the line (line1
in this case) and once I found a point that was inside the latitude or longitude of the intersecting points then I could start a new line with those coordinates that was bounded by the intersecting points.
However, this seems like a crazy amount of work. I feel like there has to be an easier solution. Especially since I have a very basic knowledge of Shapely. Any help would be greatly appreciated.
The following algorithm is for splitting a lineString in 3 segments given two intermediary points (called startPoint and endPoint) The code looks like python but must be treated more as a pseudo-code because I can not test.
linestring
is the line to be splitted
## first find in which pair the startPoint and endPoint exist
for i,e in enumerate(linestring,1):
if linestring[i-1,i].contains(startPoint):
startIdx = i-1
if linestring[i-1,i].contains(endPoint):
endIdx = i
# build three list
# startLine from the beginning of line until start point
# middleLine from startPoint until endPoint
# endLine from endPoint until the last point
# transform every list to a LineString
# start the list with coords from Line starting with beginning until startPoint
startLine = linestring.coords[:startIdx]
# append startPoint coords
startLine.append( startPoint.coords)
# transform from list to LineString
startLine = LineSting(startLine)
middleLine = list(startPoint.coords).extend(linestring.coords[startIdx+1:endIdx-1]).extend(endPoint.coord)
# transform from list to LineString
middleLine = LineSting(middleLine)
# start list with end point coords
endLine = endPoint.coords
# extend the list with coords from Line starting with endPoint until end
endLine.extend( linestring.coords[endIdx:])
# transform from list to LineString
endLine = LineSting(endLine)