【问题标题】:Need to find the intersection point of two line segments iterated over multiple segments需要在多条线段上迭代找到两条线段的交点
【发布时间】:2016-08-19 22:45:28
【问题描述】:

好的,问题来了。我试图通过比较从一系列 csv 文件中读取的多个线段来计算两条线的交点。我已经将每个线段的 x,y 坐标对放入元组内的元组列表中,如下所示:

continuousLine = [((x1,y1),(x2,y2)), ...]
crossingLines = [((x1,y1),(x2,y2)), ...]

Line Problem

我试图弄清楚如何沿着连续线和交叉线进行迭代,以找出每条交叉线沿连续线相交的位置。

基本上我想要(下面列出的伪代码):

for segment in continuousLine:
    if segment in crossingLines intersect == True:
       return intersection
    else:
       move on to next crossing line segment and repeat test

我讨厌在这方面寻求帮助,因为我对编码太陌生,无法帮助其他人,但希望有人能和我一起解决这个问题。

我确实有一种方法,我认为一旦我找出迭代器就可以计算交集:

line1 = ()
line2 = ()
def line_intersection(line1, line2):
    xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
    ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1]) #Typo was here

    def det(a, b):
        return a[0] * b[1] - a[1] * b[0]

    div = det(xdiff, ydiff)
    if div == 0:
       raise Exception('lines do not intersect')

    d = (det(*line1), det(*line2))
    x = det(d, xdiff) / div
    y = det(d, ydiff) / div
    return x, y

print line_intersection((A, B), (C, D))

【问题讨论】:

  • 你知道如何在给定端点的情况下确定两条线的交点吗?如果是这样,edit 你的问题并添加。
  • 我愿意,感谢您的建议并查看上面的帖子编辑。
  • 好极了——你可以看到你得到了一些答案。顺便说一句,我建议您 raise 一个不太通用的异常,也许是像 ValueError('lines do not intersect') 这样的特定异常,因为通用异常可以隐藏许多其他问题(例如 SyntaxErrorKeyboardInterrupt),这会使代码开发更加困难,因为调用者将不得不except Exception: 来处理不这样做的情况。

标签: python line-intersection


【解决方案1】:

由于您没有提供任何示例输入和预期输出,我将使用如下所示的line_intersection() 函数的虚拟版本。它所做的只是打印其输入并返回一个硬编码的结果——但它会向您展示如何遍历输入数据并将其传递给真正的函数。

从输出中应该清楚它在做什么。

def line_intersection(line1, line2):
    print('intersecting:')
    print('  ({}. {}), ({}, {})'.format(line1[0][0], line1[0][1],
                                        line1[1][0], line1[1][1]))
    print('  ({}. {}), ({}, {})'.format(line2[0][0], line2[0][1],
                                        line2[1][0], line2[1][1]))
    print('')
    return 100, 200

所有的循环都放在了一个名为find_intersections() 的生成器函数中,它返回找到的连续交集,跳过任何没有找到的组合。

def find_intersections(continuous_line, crossing_lines):
    for cl_segment in continuous_line:
        for xl_segment in crossing_lines:
            try:
                x, y = line_intersection(cl_segment, xl_segment)
            except Exception:
                pass
            else:
                yield x, y

这是一个使用虚构输入数据的使用示例:

continuous_line = [((1,2),(3,4)), ((5,6),(7,8)), ((9,10),(11,12))]
crossing_lines = [((21,22),(23,24)), ((25,26),(27,28)), ((29,30),(31,32))]
intersections = [(x, y) for x, y in
                    find_intersections(continuous_line, crossing_lines)]
print('intersections found:')
print(intersections)

输出:

intersecting:
  (1. 2), (3, 4)
  (21. 22), (23, 24)

intersecting:
  (1. 2), (3, 4)
  (25. 26), (27, 28)

intersecting:
  (1. 2), (3, 4)
  (29. 30), (31, 32)

intersecting:
  (5. 6), (7, 8)
  (21. 22), (23, 24)

intersecting:
  (5. 6), (7, 8)
  (25. 26), (27, 28)

intersecting:
  (5. 6), (7, 8)
  (29. 30), (31, 32)

intersecting:
  (9. 10), (11, 12)
  (21. 22), (23, 24)

intersecting:
  (9. 10), (11, 12)
  (25. 26), (27, 28)

intersecting:
  (9. 10), (11, 12)
  (29. 30), (31, 32)

intersections found:
[(100, 200), (100, 200), (100, 200), (100, 200), (100, 200), (100, 200), (100,
200), (100, 200), (100, 200)]

【讨论】:

    【解决方案2】:

    假设函数 line_intersection 将在 div == 0 上返回 False 而不是引发异常。

    简单的方法:

    filter(None, [intersection(a, b) for a in continuousLine for b in crossingLines])
    

    但是,使用嵌套循环,当crossLines中有很多段时,它会很慢。

    更有效的方法:

    要提高性能,请尝试intervaltree,它将为您提供相交候选以进行测试。在您的情况下,首先在crossingLines 上构建一个区间树,然后遍历continuousLine 以在该树中找到相交候选者,并测试以获得最终结果。

    【讨论】:

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