【问题标题】:Python intersection of two line segments not working两条线段的Python交点不起作用
【发布时间】:2016-01-11 04:23:14
【问题描述】:

我创建了这段代码来在 python 中找到 2 条线段之间的交点,但它似乎并没有为所有线产生正确的结果:

注意:我在游戏中使用它,其中 y 值会随着您的下降而增加。所以左上角是(0,0),左下角是(0,300)。不确定这是否会有所不同。

def getIntersectPoint(p1, p2, p3, p4):
    e = sys.float_info.epsilon * 1000

    # reorganize points from smaller to bigger in x-axis
    if p2[0]<p1[0]:
        p1,p2=p2,p1
    if p4[0]<p3[0]:
        p3,p4=p4,p3

    rise1 = float(p2[1]-p1[1])
    run1 = float(p2[0]-p1[0])
    if abs(run1) <= e:
        m1 = None
        b1 = float(p1[0])
    else:
        m1 = rise1/run1
        b1 = float(p1[1]-m1*p1[0])

    rise2 = float(p4[1]-p3[1])
    run2 = float(p4[0]-p3[0])
    if abs(run2) <= e:
        m2 = None
        b2 = float(p3[0])
    else:
        m2 = rise2/run2
        b2 = float(p3[1]-m2*p3[0])

    # check if lines are parallel
    if (m1==None and m2==None) or (m1!=None and m2!=None and abs(m1-m2)<=e):
        #check if they are right on top of each other
        if abs(b1-b2)<=e:
            return () # infinite points
        return None
    elif m1==None:
        iy2 = m2*b1 + b2
        ix, iy = b1, iy2
    elif m2==None:
        iy1 = m1*b2 + b1
        ix, iy = b2, iy1
    else:
        ix = (b1-b2)/(m2-m1)
        iy = m1*ix + b1

    # check if the intersection is in the bounding box
    if ix>=p1[0]-e and ix<=p2[0]+e and ix>=p3[0]-e and ix<=p4[0]+e:
        if iy>=p1[1]-e and iy<=p2[1]+e and iy>=p3[1]-e and iy<=p4[1]+e:
            return [ix, iy]

    return None

在p1,p2,p3,p4格式中找不到交集时生成的一些测试用例:

[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [440, 0]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 0] [0, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [0, 280] [440, 280]
[-545.901858671, 443.161842698] [198.177615767, 149.315393477] [440, 0] [440, 280]

有谁知道怎么回事?

谢谢

【问题讨论】:

  • 这无疑是一种测试线相交的创造性方法;我建议使用谷歌搜索更标准的线交叉点方法,并以此构建您的解决方案。
  • 一些代码 cmets、测试用例和预期/失败输出会很有用
  • 好的,我添加了一些失败的案例。
  • this question的回答中给出了一个很好的方法。

标签: python geometry line


【解决方案1】:

您遇到的问题是,您有时会根据 x 值交换线段端点的顺序。但这也改变了 y 值的顺序,因此您对“边界框”内的交点的测试失败。您可以尝试以下方法进行检查:

# check if the intersection is in the bounding box
    if ix>=p1[0]-e and ix<=p2[0]+e and ix>=p3[0]-e and ix<=p4[0]+e:
        y1, y2, y3, y4 = p1[1], p2[1], p3[1], p4[1]
        if y2 < y1:
            y2, y1 = y1, y2
        if y4 < y3:
            y4, y3 = y3, y4
        if iy>=y1-e and iy<=y2+e and iy>=y3-e and iy<=y4+e:
                return [ix, iy]

【讨论】:

    猜你喜欢
    • 2021-10-29
    • 2020-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多