两个线段距离的一个定理证明 和代码实现.

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

posted on 2024-05-21 17:46  张博的博客  阅读(16)  评论(0编辑  收藏  举报

导航