python 两直线距离 垂线中点法

需求:求两条直线的距离

方法:通过两条直线上的两个点分别向另一条直线做垂线,两个垂点的中心点连接作为距离。

如下图:黑线表示待求的两条直线间的距离,红线表示右侧直线向左侧直线的垂线,蓝线表示左侧直线向右侧直线的垂线,紫线表示两条直线上垂点中点的连线(代表距离)。

实现代码:

import math
import cv2
def intersectionLines(a1, a2, b1, b2):
    return (
          ((a1[0] * a2[1]  -  a1[1] * a2[0]) * (b1[0] - b2[0]) -
           (b1[0] * b2[1]  -  b1[1] * b2[0]) * (a1[0] - a2[0])) /
          ((a1[0] - a2[0]) * (b1[1] - b2[1]) -
           (a1[1] - a2[1]) * (b1[0] - b2[0])),
          ((a1[0] * a2[1]  -  a1[1] * a2[0]) * (b1[1] - b2[1]) -
           (b1[0] * b2[1]  -  b1[1] * b2[0]) * (a1[1] - a2[1])) /
          ((a1[0] - a2[0]) * (b1[1] - b2[1]) -
           (a1[1] - a2[1]) * (b1[0] - b2[0]))
          )
def p_to_l(point,l_p1,l_p2):
    if l_p1[0]-l_p2[0]==0:
        crop=(l_p1[0],point[1])
        # print("crop",crop)
    elif l_p1[1]-l_p2[1]==0:
        crop=(point[0],l_p1[1])
    else:
        k_l=(l_p1[1]-l_p2[1])/(l_p1[0]-l_p2[0])
        # print(k_l)
        k=-1/k_l
        # print(k)
        b=point[1]-k*point[0]
        # print(b)
        x=l_p1[0]
        # print(x)
        y=k*x+b
        point2=(x,y)
        # print(point)
        # print(point2)
        # print(l_p1,l_p2)
        crop=intersectionLines(point, point2, l_p1, l_p2)
    return crop
def p_to_distance(p1,p2):
    return math.sqrt((p1[0]-p2[0])**2+(p1[1]-p2[1])**2)


def to_overlap_pts(a1, a2, b1,b2):
    if a1[1]>a2[1]:
        l1_hight=a1
        l1_low=a2
    else:
        l1_hight=a2
        l1_low=a1
    if b1[1]>b2[1]:
        l2_hight=b1
        l2_low=b2
    else:
        l2_hight=b2
        l2_low=b1
    

    l1_p1, l1_p2, l2_p1, l2_p2 = (0., 0.), (0., 0.), (0., 0.), (0., 0.)
    point1_state=0
    point2_state=0
    #直线没有重合部分l1
    l1_l=p_to_l(l1_low,l2_low,l2_hight)

    l1_h=p_to_l(l1_hight,l2_low,l2_hight)
    # print("l1",l1_h)
    # print("l2_low",l2_low)
    # print("l2_hight",l2_hight)
    list=[l2_low[0],l2_hight[0]]
    l=min(list)
    r=max(list)
    if l<=l1_h[0]<=r:
        point1_state=1
    if l<=l1_l[0]<=r:
        point2_state=1
    print("state",point1_state,point2_state)
    if point1_state==0 and point2_state==0:
        print("框选错误,请重新框选")
    else:
        l1_b=0
        l1_t=0
        l2_b=0
        l2_t=0
        #左边直线
        if l2_low[0]<l2_hight[0]:
            l=l2_low[0]
            r=l2_hight[0]
        else:
            r = l2_low[0]
            l = l2_hight[0]

        cro_p1 = p_to_l(l1_low, l2_low, l2_hight)
        if l<=cro_p1[0]<=r:
            p1=l1_low
            p2=cro_p1
            cro_p1 = (cro_p1[0], cro_p1[1])
            l1_b=1
        else:
            pass
        cro_p2 = p_to_l(l1_hight, l2_low, l2_hight)
        if l<=cro_p2[0]<=r:

            p1=l1_hight
            p2=cro_p2
            cro_p2 = (cro_p2[0], cro_p2[1])
            l1_t=1
        else:
            pass

        #右边直线
        if l1_low[0]<l1_hight[0]:
            l=l1_low[0]
            r=l1_hight[0]
        else:
            r= l1_low[0]
            l = l1_hight[0]
        cro_p3 = p_to_l(l2_low, l1_low, l1_hight)
        if l<=cro_p3[0]<=r:
            p1=l2_low
            p2=cro_p3
            cro_p3 = (cro_p3[0], cro_p3[1])
            l2_b=1
        else:
            pass
        cro_p4 = p_to_l(l2_hight, l1_low, l1_hight)
        if l<=cro_p4[0]<=r:
            p1=l2_hight
            p2=cro_p4
            cro_p4 = (cro_p4[0], cro_p4[1])
            l2_t=1
        else:
            pass
        #右直线投影到左直线
        if l1_b+l1_t==0 and l2_b+l2_t==2:
            l1_p1=cro_p3
            l1_p2=cro_p4
            l2_p1=l2_low
            l2_p2=l2_hight
       #左直线投影到右直线
        elif l1_b+l1_t==2 and l2_b+l2_t==0:
            l1_p1=l1_low
            l1_p2=l1_hight
            l2_p1=cro_p1
            l2_p2=cro_p2
        #右直线投影到作直线,左直线一个点投影到右直线
        elif l1_b + l1_t == 1 and l2_b + l2_t == 2:
            #左直线上点
            if l1_t == 1:
                l2_p1 = l2_low
                l2_p2 = cro_p2
            #左直线下
            else:
                l2_p1 = cro_p1
                l2_p2 = l2_hight
            l1_p1 = cro_p3
            l1_p2 = cro_p4
        #左直线投影到右直线,右直线一个点投影到左直线
        elif l1_b + l1_t == 2 and l2_b + l2_t == 1:
            #右直线上点
            if l1_t == 1:
                l1_p1 = l1_low
                l1_p2 = cro_p4
            #右直线下点
            else:
                l1_p1 = cro_p3
                l1_p2 = l1_hight
            l2_p1 = cro_p1
            l2_p2 = cro_p2
        elif l1_b == 1 and l2_t == 1:
            l1_p1 = l1_low
            l1_p2 = cro_p4
            l2_p1 = cro_p1
            l2_p2 = l2_hight
        elif l1_t == 1 and l2_b == 1:
            l1_p1 = cro_p3
            l1_p2 = l1_hight
            l2_p1 = l2_low
            l2_p2 = cro_p2

    return l1_p1, l1_p2, l2_p1, l2_p2

def coincidence_part(a1, a2, b1,b2):
    # img=cv2.imread("1030_1_undistorted.png")

    if a1[1]>a2[1]:
        l1_hight=a1
        l1_low=a2
    else:
        l1_hight=a2
        l1_low=a1
    if b1[1]>b2[1]:
        l2_hight=b1
        l2_low=b2
    else:
        l2_hight=b2
        l2_low=b1
    #直线没有重合部分l1

    if l1_hight[1]<=l2_low[1] or l1_low[1]>=l2_hight[1]:
        print("框选错误,请重新框选")
    else:
        l1_b=0
        l1_t=0
        l2_b=0
        l2_t=0
        #左边直线
        if l2_low[0]<l2_hight[0]:
            l=l2_low[0]
            r=l2_hight[0]
        else:
            r = l2_low[0]
            l = l2_hight[0]

        cro_p1 = p_to_l(l1_low, l2_low, l2_hight)
        if l<=cro_p1[0]<=r:
            p1=l1_low
            p2=cro_p1
            cro_p1 = (cro_p1[0], cro_p1[1])
            l1_b=1
        else:
            pass
        cro_p2 = p_to_l(l1_hight, l2_low, l2_hight)
        if l<=cro_p2[0]<=r:

            p1=l1_hight
            p2=cro_p2
            cro_p2 = (cro_p2[0], cro_p2[1])
            l1_t=1
        else:
            pass

        #右边直线
        if l1_low[0]<l1_hight[0]:
            l=l1_low[0]
            r=l1_hight[0]
        else:
            r= l1_low[0]
            l = l1_hight[0]
        cro_p3 = p_to_l(l2_low, l1_low, l1_hight)
        if l<=cro_p3[0]<=r:
            p1=l2_low
            p2=cro_p3
            cro_p3 = (cro_p3[0], cro_p3[1])
            l2_b=1
        else:
            pass
        cro_p4 = p_to_l(l2_hight, l1_low, l1_hight)
        if l<=cro_p4[0]<=r:
            p1=l2_hight
            p2=cro_p4
            cro_p4 = (cro_p4[0], cro_p4[1])
            l2_t=1
        else:
            pass
        #右直线投影到左直线
        if l1_b+l1_t==0 and l2_b+l2_t==2:
            l1_p1=cro_p3
            l1_p2=cro_p4
            l2_p1=l2_low
            l2_p2=l2_hight
       #左直线投影到右直线
        elif l1_b+l1_t==2 and l2_b+l2_t==0:
            l1_p1=l1_low
            l1_p2=l1_hight
            l2_p1=cro_p1
            l2_p2=cro_p2
        #右直线投影到作直线,左直线一个点投影到右直线
        elif l1_b + l1_t == 1 and l2_b + l2_t == 2:
            #左直线上点
            if l1_t == 1:
                l2_p1 = l2_low
                l2_p2 = cro_p2
            #左直线下
            else:
                l2_p1 = cro_p1
                l2_p2 = l2_hight
            l1_p1 = cro_p3
            l1_p2 = cro_p4
        #左直线投影到右直线,右直线一个点投影到左直线
        elif l1_b + l1_t == 2 and l2_b + l2_t == 1:
            #右直线上点
            if l1_t == 1:
                l1_p1 = l1_low
                l1_p2 = cro_p4
            #右直线下点
            else:
                l1_p1 = cro_p3
                l1_p2 = l1_hight
            l2_p1 = cro_p1
            l2_p2 = cro_p2
        elif l1_b == 1 and l2_t == 1:
            l1_p1 = l1_low
            l1_p2 = cro_p4
            l2_p1 = cro_p1
            l2_p2 = l2_hight
        elif l1_t == 1 and l2_b == 1:
            l1_p1 = cro_p3
            l1_p2 = l1_hight
            l2_p1 = l2_low
            l2_p2 = cro_p2


        # print(l1_b, l1_t, l2_b, l2_t)
        # print(l1_p1,l1_p2,l2_p1,l2_p2)
        l1_c = ((l1_p1[0] + l1_p2[0])/ 2, (l1_p1[1] + l1_p2[1]) / 2)
        l1_to_l2=p_to_l(l1_c,l2_p1,l2_p2)
        l1_to_l2=(l1_to_l2[0],l1_to_l2[1])

        l2_c = ((l2_p1[0] + l2_p2[0]) / 2, (l2_p1[1] + l2_p2[1]) / 2)
        # print(l2_c,l1_p1,l1_p2)

        l2_to_l1=p_to_l(l2_c,l1_p1,l1_p2)
        l2_to_l1 = (int(l2_to_l1[0]), int(l2_to_l1[1]))

        l1=p_to_distance(l1_c,l1_to_l2)
        l2=p_to_distance(l2_c,l2_to_l1)
        # print(l1,l2)
        distance=(l1+l2)/2

        # print(distance)
        return distance
# coincidence_part((200,100),(200,600),(800,100),(800,621))
# coincidence_part((100,100),(600,100),(200,400),(500,400))
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值