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

image

複雜度O(1)

#計算兩個線段之間的最短距離:
#暴力遍歷兩邊所有點求點之間距離最小速度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]))

測試兩條直線的夾角 11.309932474020215
測試點跟直線的交點 [-0.5, 0.5]
測試點跟直線的距離 0.7071067811865476
測試點跟線段的距離 2.23606797749979
測試線段跟線段的距離 3.605551275463989

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章