判断两个封闭多边形的关系

算法描述:
将文件中线段两端点的坐标储存在两个多边形列表内,分别判断各边有无交点,若无交点,分别计算:(1)多边形A的点到多边形B的点的距离(2)多边形A的点到多边形B的边的距离(3)多边形B的点到多边形A的边的距离,计算点到线段的距离时,先过点作垂直于线段的直线,并判断直线与线段是否相交,若相交,则利用距离公式计算,否则此距离为无效距离,予以舍弃,最后取最小距离作为两个多边形的距离。

#判断两个封闭多边形的关系,并求其最小间距
def Readf():#读取文件
    ls = []
    ls1 = []
    ls2 = []
    lines = open("Polygon.txt").readlines()
    for line in lines:
        line = line.strip('\n').split(',')
        if line[0] == 'A1':
            ls1.append([(eval(line[1]),eval(line[2])),(eval(line[3]),eval(line[4]))])
        elif line[0] == 'A2':
            ls2.append([(eval(line[1]),eval(line[2])),(eval(line[3]),eval(line[4]))])
    return ls1, ls2

def Ltol(line1, line2):#判断两线段相交
    x1,y1 = line1[0][0],line1[0][1]
    x2,y2 = line1[1][0],line1[1][1]
    x3,y3 = line2[0][0],line2[0][1]
    x4,y4 = line2[1][0],line2[1][1]
    if x1 > x2:#将x坐标小的点放在第一项
        x1,y1,x2,y2 = x2,y2,x1,y1
    if x3 > x4:
        x3,y3,x4,y4 = x4,y4,x3,y3
    if (x1>x4) or (x2<x3):#无公共区间则无交点
        return 0
    xmin, xmax = max(x1, x3), min(x2, x4)#求公共区间
    try:
        k1 = (y1-y2)/(x1-x2)#计算斜率
    except:#l1斜率无穷
        k1 = 0#不改变端点取值
    try:
        k2 = (y3-y4)/(x3-x4)
    except:#l2斜率无穷
        k2 = 0
    y1 = y1 + k1 * (xmax - x1)  #求出区间端点值
    y2 = y2 + k1 * (xmin - x2)
    y3 = y3 + k2 * (xmax - x3)
    y4 = y4 + k2 * (xmin - x4)
    if (x1==x2 and x3==x4):#处理斜率无穷大,若有一条线段斜率有限,变换后将成为一点
        if (max(y1,y2)<min(y3,y4)) or (min(y1,y2)>max(y3,y4)):
            return 0
        else:
            return 1
    if (max(y1,y2)<min(y3,y4)) or (min(y1,y2)>max(y3,y4)):#根据端点值判断相交
        return 0
    else:
        return 1

def Potopo(po1, po2):#判断两多边形相交
    for l1 in po1:
        for l2 in po2:
            if Ltol(l1, l2):
                return 1
    return 0

def Dpp(p1, p2):#计算两点距离
    d = pow(p1[0]-p2[0],2) + pow(p1[1]-p2[1],2)
    d = pow(d,0.5)
    return d

def Dpl(p, l):#计算点到线段距离
    l_p = 10000#当线段长度超过此值时看作直线
    x1,y1 = l[0][0],l[0][1]
    x2,y2 = l[1][0],l[1][1]
    if (x1 == x2):#线段竖直
        if (p[1]>=min(y1,y2)) and (p[1]<=max(y1,y2)):
            return abs(p[0]-x1)
        else:
            return l_p#无效距离
    if (y1 == y2):#线段水平
        if (p[0]>=min(x1,x2)) and (p[0]<=max(x1,x2)):
            return abs(p[1]-y1)
        else:
            return l_p#无效距离
    A = y2 - y1#求线段参数
    B = x1 - x2
    C = x1*(y1-y2) + y1*(x2-x1)
    k = B/A#过点作与线段垂直的直线
    line = [[p[0]-l_p,p[1]-k*l_p],[p[0]+l_p,p[1]+k*l_p]]
    if Ltol(line, l):
        return abs(A*p[0]+B*p[1]+C)/pow(A*A+B*B,0.5)
    else:
        return l_p  #若直线与线段不相交则为无效距离

ls1, ls2 = Readf()
if Potopo(ls1, ls2):
    print("两多边形相交")
else:
    dmin = Dpp(ls1[0][0], ls2[0][0])
    for l1 in ls1:
        for l2 in ls2:
            d1 = Dpp(l1[0], l2[0])#多边形A点到多边形B点的距离
            d2 = Dpl(l1[0], l2)#多边形A点到多边形B边的距离
            d3 = Dpl(l2[0], l1)#多边形B点到多边形A边的距离
            if min(d1, d2, d3) < dmin:
                dmin = min(d1, d2, d3)
    if dmin:
        print("两多边形不相交,最小间距{:.2f}".format(dmin))
    else:
        print("两多边形相交")



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值