# 兩個線段距離的一個定理證明 和代碼實現.

``````#計算兩個線段之間的最短距離:
#暴力遍歷兩邊所有點求點之間距離最小速度N方.

import cv2,math
def jiajiao(line1, line2):
line1with_x_axis=math.atan((-line1[3]+line1[1])/(line1[2]-line1[0]))/math.pi*180 if line1[2]!=line1[0] else 90
line2with_x_axis=math.atan((-line2[3]+line2[1])/(line2[2]-line2[0]))/math.pi*180 if line2[2]!=line2[0] else 90
aaa= abs(line1with_x_axis-line2with_x_axis)
return  aaa if aaa<90 else 180-aaa
pass

pass

def cross_point(line1, line2):  # 計算交點函數======雙點型直線.
#是否存在交點
point_is_exist=False
x=0
y=0
x1 = line1[0]  # 取四點座標
y1 = line1[1]
x2 = line1[2]
y2 = line1[3]

x3 = line2[0]
y3 = line2[1]
x4 = line2[2]
y4 = line2[3]

if (x2 - x1) == 0:
k1 = None
else:
k1 = (y2 - y1) * 1.0 / (x2 - x1)  # 計算k1,由於點均爲整數，需要進行浮點數轉化
b1 = y1 * 1.0 - x1 * k1 * 1.0  # 整型轉浮點型是關鍵

if (x4 - x3) == 0:  # L2直線斜率不存在操作
k2 = None
b2 = 0
else:
k2 = (y4 - y3) * 1.0 / (x4 - x3)  # 斜率存在操作
b2 = y3 * 1.0 - x3 * k2 * 1.0

if k1 is None:
if not k2 is None:
x = x1
y = k2 * x1 + b2
point_is_exist=True
elif k2 is None:
x=x3
y=k1*x3+b1
elif not k2==k1:
x = (b2 - b1) * 1.0 / (k1 - k2)
y = k1 * x * 1.0 + b1 * 1.0
point_is_exist=True
return point_is_exist,[x, y]

def cross_point_of_line_and_point(line1,point):
#給一個線段和一個點.計算他們之間的最短距離.
#思路: 算點到直線的距離,看交點是否在線段上,不在線段上,就算2次兩點距離就完事了.
#計算點斜式.
x1 = line1[0]  # 取四點座標
y1 = line1[1]
x2 = line1[2]
y2 = line1[3]

if (x2 - x1) == 0:
k1 = None #豎直的直線.
else:
k1 = (y2 - y1) * 1.0 / (x2 - x1)  # 計算k1,由於點均爲整數，需要進行浮點數轉化
if not k1:
k2=0
else:
k2=-1/k1
line2=[point[0],point[1],point[0]+1,point[1]+k2]
point_is_exist,[x, y]=cross_point(line1,line2)
return [x,y]

def distance_of_line_and_point(line1,point):
#給一個線段和一個點.計算他們之間的最短距離.
#思路: 算點到直線的距離,看交點是否在線段上,不在線段上,就算2次兩點距離就完事了.
#計算點斜式.
x1 = line1[0]  # 取四點座標
y1 = line1[1]
x2 = line1[2]
y2 = line1[3]

if (x2 - x1) == 0:
k1 = None #豎直的直線.
else:
k1 = (y2 - y1) * 1.0 / (x2 - x1)  # 計算k1,由於點均爲整數，需要進行浮點數轉化
if not k1:
k2=0
else:
k2=-1/k1
line2=[point[0],point[1],point[0]+1,point[1]+k2]
point_is_exist,[x, y]=cross_point(line1,line2)

return  ((point[0]-x)**2+  (point[1]-y)**2  )**0.5

def distance_of_point_and_segment_line(line1,point):
#給一個線段和一個點.計算他們之間的最短距離.
#思路: 算點到直線的距離,看交點是否在線段上,不在線段上,就算2次兩點距離就完事了.
#計算點斜式.
x1 = line1[0]  # 取四點座標
y1 = line1[1]
x2 = line1[2]
y2 = line1[3]

if (x2 - x1) == 0:
k1 = None #豎直的直線.
else:
k1 = (y2 - y1) * 1.0 / (x2 - x1)  # 計算k1,由於點均爲整數，需要進行浮點數轉化
if not k1:
k2=0
else:
k2=-1/k1
line2=[point[0],point[1],point[0]+1,point[1]+k2]
point_is_exist,[x, y]=cross_point(line1,line2)
if x>=min(line1[0],line1[2]) and x<=max(line1[0],line1[2]): #交點在直線上.
disc=  ((point[0]-x)**2+  (point[1]-y)**2  )**0.5
return disc
else:
disc1=((point[0]-line1[0])**2+  (point[1]-line1[1])**2  )**0.5
disc2=((point[0]-line1[2])**2+  (point[1]-line1[3])**2  )**0.5
return min(disc1,disc2)

def compute_dis_of_two_segment_line(line1,line2):
# line1: [x1,y1,x2,y2] 用2個端點,四個數來表示一個直線
disc1=distance_of_point_and_segment_line(line1,[line2[0],line2[1]])
disc2=distance_of_point_and_segment_line(line1,[line2[2],line2[3]])
disc3=distance_of_point_and_segment_line(line2,[line1[0],line1[1]])
disc4=distance_of_point_and_segment_line(line2,[line1[2],line1[3]])

return min(disc1,disc2,disc3,disc4)
pass

if __name__ =='__main__':

print('測試兩條直線的夾角',jiajiao([1,2,3,4],[6,2,8,5]))

print('測試點跟直線的交點',cross_point_of_line_and_point([1,2,3,4],[0,0]))
print('測試點跟直線的距離',distance_of_line_and_point([1,2,3,4],[0,0]))
print('測試點跟線段的距離',distance_of_point_and_segment_line([1,2,3,4],[0,0]))
#=========根據我博客上面的定理, 兩個線段之間的距離等價於四個點到直線的距離取min即可.
print('測試線段跟線段的距離',compute_dis_of_two_segment_line([1,2,3,4],[6,2,8,5]))
``````