检查同一圆上的两个段是否重叠/相交

时间:2012-08-02 10:18:41

标签: algorithm language-agnostic geometry 2d angle

给定同一圆圈的两个圆弧段:A = [a1,a2]和B = [b1,b2],其中:

  • a1,a2,b1,b2在-inf和+ inf之间的度数
  • a1< = a2; b1< = b2
  • A2-A1&LT = 360; B2-B1< = 360

如何判断这两个圆弧段是否重叠? (即如果他们相交或触摸至少一点)

示例:

A=[  -45°,    45°]; B=[   10°,   20°] ==> overlap
A=[  -45°,    45°]; B=[   90°,  180°] ==> no overlap
A=[  -45°,    45°]; B=[  180°,  360°] ==> overlap
A=[ -405°,  -315°]; B=[  180°,  360°] ==> overlap
A=[-3600°, -3601°]; B=[ 3601°, 3602°] ==> overlap (touching counts as overlap)
A=[ 3600°,  3601°]; B=[-3601°,-3602°] ==> overlap (touching counts as overlap)
A=[    -1°,    1°]; B=[ 3602°, 3603°] ==> no overlap 

这看起来像一个看似简单的问题,但我无法绕过它。 我目前有一个基本的想法,一个解决方案,如果它跨越0°,将每个段分成两个,但我不确定是否涵盖所有情况,我想知道是否有一个优雅的公式。

4 个答案:

答案 0 :(得分:10)

正如@admaoldak所提到的,首先将度数标准化:

a1_norm = a1 % 360
a2_norm = a2 % 360
b1_norm = b1 % 360
b2_norm = b2 % 360

现在检查b1是否在(a1,a2),

之内
def intersect(b, as, ae
    Intersect = False
    If as > ae:
        if b >= as or b <= ae:
            return True
    Else:
        if b>=as and b<=ae:
            return True
    return False

最后的答案是:

intersect(b1_norm,a1_norm,a2_norm)||intersect(b2_norm,a1_norm,a2_norm)||
intersect(a1_norm,b1_norm,b2_norm)||intersect(a2_norm,b1_norm,b2_norm)

答案 1 :(得分:2)

对于区间[i.X,i.Y],让我们定义标准化 i_norm = normalize(i),以便:

1. 0 <= i_norm.X < 360
2. i_norm.X <=i_norm.Y

然后我们定义另一个操作 i_slide = slide(i),以便:

1. i_slide.X = i.X + 360
2. i_slide.Y = i.Y + 360

我们可以证明, 输入 A B A 圈重叠 B 如果和只有在:

  使用规范化(B)

规范化(A) 间隔重叠      

     使用幻灯片(规范化(B))

规范化(A) 间隔重叠

区间重叠的定义方式与adamoldak帖子中的“交集”相同。

并且操作 normalize() slide()都很容易实现。

举个例子:A=[-45°,45°]; B=[10°,20°],我们有

normalize(A) = [315,405] 
normalize(B) = [10,20] 
slide( normalize(B) ) = [370,380]

和[315,405] 区间重叠与[370,380]

答案 2 :(得分:0)

如何将每个度数值标准化为0-360:

a1_norm = a1 % 360
a2_norm = a2 % 360
b1_norm = b1 % 360
b2_norm = b2 % 360

然后你只检查交叉点:

(a1_norm <= b2_norm) and (a2_norm<= b1_norm) 

答案 3 :(得分:0)

我在一个游戏引擎中遇到了类似的问题,其中矩形在循环地图中重叠。我想了很多,也看了你们一些人的回答。如果你正在寻找性能,这是你能得到的最好的(直到有人证明我错了:P):

#assume the angles are already normalised
def overlap(a1, a2, b1, b2):
  if a2 - a1 + b2 - b1 > 360: #must overlap
    return True
  return (b1 > a2) ^ (b2 > a1) ^ (a2 < a1) ^ (b2 < b1)

优雅。优雅,有点丑。