Here is how I would structure my algorithm. I am assuming the target points and the measured points are 'linear' (that I don't go backwards at any point).
Step 1: Defining the virtual segments
You know from Calculating the distance between a point and a virtual line of two lat/lngs how to determine the distance of a point from a virtual line. So you can think of your list of target points instead as a series of virtual lines. Assuming your target points are provided in an array of x,y pairs targetCoords
, if you have n = len(targetCoords)
target points, then you will have n-1
virtual segments.
For each point in your target points, determine it's distance from the next target point. You can do this with a simple list comprehension:
targetPointDistances = [(Dist(Coords2,Coords1) for Coords1, Coords2 in zip(targetCoords[:-1], targetCoords[1:])]
"Dist" is a user defined function to determine the distance between coordinate pairs. This question gives an example of how to easily implement this, while this question gives detail on the more precise Vincenty formula.
Step 2: Determining the current virtual segment
You want to start looking at each measured point, and comparing it's distance from a virtual segment. For each point, you want to check that you're still comparing it to the proper virtual segment.
So, check that you're in the correct segment before doing each distance determination. Let's try this:
targetSegment = 0
for point in measuredPoints:
while Dist(point, targetCoords[targetSegment+2]) < targetPointDistances[targetSegment+1]:
targetSegment += 1
For each point, I'm checking to see if its distance from the end point of the next segment is less than the length of the current segment. If this is true, I start comparing it to the next virtual segment. (Extra credit: are there any cases where this won't work, or would be suboptimal?)
In your example image, this leaves the first 4 measured points in the first segment. The fifth measured point is closer to the third target point than the second target point is to the third target point, so we advance to the next virtual segment.
Step 3: Calculate the distance from the virtual line
This seems to be pretty straightforward - you already linked to this!
Just use targetCoords[targetSegment]
and targetCoords[targetSegment+1]
as the starting and ending points for your virtual line. This can be part of the for loop in step 2!