I want to make a function to get the closest/shortest distance between any two lines (assuming they don't intersect). I know there are several posts about the shortest distance between a point and a line, but I couldn't find any for two lines.
I have consulted several math and vector learning sites and managed to crack out the algorithm below. It gives an answer, but not the correct one. For instance, when finding the shortest distance between:
l1 = [(5,6),(5,10)]
l2 = [(0,0),(10,10)]
print _line2line(l1,l2)
...it gives the answer as...
5.75223741636
As can be seen in the graph of the two lines (it shows a 10x10 frame with ticks mark every 1 unit) and theoretically speaking, the distance should be much smaller, around 1, between the points (6,5) and (5,5).
So I'm wondering if anyone can spot what I'm doing wrong in my code? (If possible I would also like to know how to get the actual points where the two lines are closest...)
Notes on the code below: L1 and L2 stands for line1 and line2, and x/y1 vs x/y2 being the start and endpoints of each line, respectively. The suffixes dx and dy stands for the delta or x and y, ie the vector if its origin is at 0,0.
def _line2line(line1, line2):
"""
- line1 is a list of two xy tuples
- line2 is a list of two xy tuples
References consulted:
http://mathforum.org/library/drmath/view/51980.html
and http://mathforum.org/library/drmath/view/51926.html
and https://answers.yahoo.com/question/index?qid=20110507163534AAgvfQF
"""
import math
#step1: cross prod the two lines to find common perp vector
(L1x1,L1y1),(L1x2,L1y2) = line1
(L2x1,L2y1),(L2x2,L2y2) = line2
L1dx,L1dy = L1x2-L1x1,L1y2-L1y1
L2dx,L2dy = L2x2-L2x1,L2y2-L2y1
commonperp_dx,commonperp_dy = (L1dy - L2dy, L2dx-L1dx)
#step2: normalized_perp = perp vector / distance of common perp
commonperp_length = math.hypot(commonperp_dx,commonperp_dy)
commonperp_normalized_dx = commonperp_dx/float(commonperp_length)
commonperp_normalized_dy = commonperp_dy/float(commonperp_length)
#step3: length of (pointonline1-pointonline2 dotprod normalized_perp).
# Note: According to the first link above, it's sufficient to
# "Take any point m on line 1 and any point n on line 2."
# Here I chose the startpoint of both lines
shortestvector_dx = (L1x1-L2x1)*commonperp_normalized_dx
shortestvector_dy = (L1y1-L2y1)*commonperp_normalized_dy
mindist = math.hypot(shortestvector_dx,shortestvector_dy)
#return results
result = mindist
return result