检查两条线(每条线都有起始位置)是否在python中重叠

时间:2014-11-28 04:55:04

标签: python algorithm

我有以下两组位置,每组位对应于开始和结束位置:

line T: t1-t2   (t1 = start_pos, t2 = end_pos)
line S: s1-s2   (s1 = start_pos, t2 = end_pos)

我想用Python编写算法来检查T是否与S相交。

示例1:

   t1-t2=55-122 and s1-s2=58-97
          s1------------s2
        t1-----------------t2
    This should return True

示例2:

 t1-t2=4-66 / t1-t2=143-166  and s1-s2=80-141
        s1----s2
 t1--t2          t1---t2
Both instances of T should return False

但为什么这段代码失败了:

def is_overlap(pos, dompos):
    """docstring for is_overlap"""
    t1,t2 = [int(x) for x in pos.split("-")]
    s1,s2 = [int(x) for x in dompos.split("-")]

    # Here we define the instance of overlapness
    if (t1 >= s1 and t2 >= s2) or \
       (t1 >= s1 and t2 <= s2) or \
       (t1 <= s1 and t2 >= s2) or \
       (t1 <= s1 and t2 <= s2):
        return True
    else:
        return False

输出:

In [2]: is_overlap('55-122', '58-97')
Out[2]: True

In [3]: is_overlap('4-66', '80-141')
Out[3]: True

In [4]: is_overlap('143-166', '80-141')
Out[4]: True

这样做的正确方法是什么?

3 个答案:

答案 0 :(得分:7)

考虑范围[a, b]和另一范围[x, y]。它们要么重叠,要么是分开的。

如果它们是分开的,那么两件事中的一件必须是真的:

  • [a, b]位于[x, y]左侧,或
  • [x, y]位于[a, b]
  • 的左侧

如果[a, b]位于[x, y]左侧,我们会b < x

如果[x, y]位于[a, b]左侧,我们会y < a

如果这些都不属实,则跨度不能分开。它们必须重叠。

此逻辑在以下函数中实现。

def are_separate(r, s):  # r and s are ordered pairs
  (a, b) = r
  (x, y) = s
  if b < x or y < a:
    return True
  else:
    return False

更简洁:

def are_separate(r, s):
  (a, b) = r
  (x, y) = s
  return b < x or y < a

更简洁:

def are_separate(r, s):
  return r[1] < s[0] or s[1] < r[0]

如果你想要相反的函数are_overlapping,只需否定表达式:

def are_overlapping(r, s):
  return not(r[1] < s[0] or s[1] < r[0])

这在逻辑上等同于:

def are_overlapping(r, s):
  return r[1] >= s[0] and s[1] >= r[0]

答案 1 :(得分:1)

你的条件错了;再次检查它们。例如,第一个条件意味着(t_1, t_2) = (100, 200)(s_1, s_2) = (50, 60)是一组有效的重叠线。但显然,他们不是。

您可能想要考虑的其他事情是用户是否向后输入坐标。如果他输入类似'80-30'的内容怎么办?

答案 2 :(得分:1)

对于那些想要在二维中使用两行的人来说,@ michael的答案是不够的。以下代码基于在代码上方列出的Wikipedia页面中找到的等式,以及一些毕达哥拉斯来检查适当点之间的交点。 https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection

x1, y1, x2, y2 = 200, 200, 300, 300
x3, y3, x4, y4 = 200, 150, 300, 350

px = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / \
     ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
py = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / \
     ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))

if ((x1 - px) ** 2 + (y1 - py) ** 2) ** 0.5 + ((x2 - px) ** 2 + (y2 - py) ** 2) ** 0.5 == \
        ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5 and \
        ((x3 - px) ** 2 + (y3 - py) ** 2) ** 0.5 + ((x4 - px) ** 2 + (y4 - py) ** 2) ** 0.5 == \
        ((x3 - x4) ** 2 + (y3 - y4) ** 2) ** 0.5:
    print("Overlap at point: (%s, %s)" % (px, py))
else:
    print("No overlap.")