检测2种不同的多边形自相交情况(相交发生在内部或外部)

时间:2019-01-04 23:58:00

标签: algorithm geometry polygon

我正在编写一种算法,将复杂(自相交)的多边形分为一个或多个简单多边形,以便可以在我的碰撞检测算法中使用它们。这可以通过添加/删除顶点并创建新的多边形来完成。

为此,我检测了多边形中的所有线段交点并按较低的交点x对其进行排序,然后按顺序处理每个线段交点。但是,可能发生两种类型的相交,并且我需要根据发生的类型对多边形进行不同的拆分。这是两种可能情况的说明:

enter image description here

我已经知道应该如何处理每种交叉点类型,但是我不知道如何检测给定的交叉点是否对应于情况1或情况2。是否有确定方法?我拥有算法所需的所有信息(顶点及其顺序,导致它们的交点和线段,...)。

假设在点Q,线段(P_i,P_i + 1)和(P_j,P_j + 1)之间有一个交点,且j> i。

情况1:我将多边形分为2个多边形,[Q,P_i + 1,...,P_j,Q]和[Q,P_j + 1,...,P_i,问]。

情况2:我在多边形中插入一个顶点V,结果多边形为[P1,...,P_i,V,P_i + 1,...,P_j,Q, P_j + 1,...,P1]

因此,我需要的丢失信息是找出由[Q,P_i + 1,...,P_j]形成的循环是“外部”循环(情况1)还是“内部”循环(情况2)。

我已经阅读了有关由循环形成的多边形的有符号区域的知识,但并没有全部理解。我不是在寻找最有效的算法,只是一种可行的算法。谢谢!

2 个答案:

答案 0 :(得分:1)

如果在交叉点将复杂的多边形拆分为简单的多边形;然后:

  • 情况1:简单的多边形不重叠

  • 情况2:简单多边形重叠,并且简单多边形之一实际上是“反多边形”(描述要排除的内容,而不是描述要包括的内容)。

可以通过“是在一个多边形内的一个多边形中的所有顶点都在另一个多边形内还是触摸另一个多边形”来确定差异。

请注意,对于第2种情况,您可能可以将一个多边形重新插入另一个多边形中,从而得到一个简单的多边形(例如,对于您的图表,您最终会遇到“ P1,交集,P3,P2,交集, P4,P5,P6”)。

但是,您忽略了更多情况。例如,从第二张图开始(对于案例2),向上拖动P3,使其位于从P6到P1的线的上方(导致在涉及P3的两条边的任一侧上没有多边形)。再举一个例子,考虑一个具有六个顶点的“图8”,其中在中间有两个相同的边(可以通过删除两个中间边将其转换为简单的矩形)。

为获得更多乐趣,请考虑以下类似操作(但不带外圈):

https://quiabsurdum.com/wp-content/uploads/2016/11/Twelve-pointed-pentagram.png

在大多数情况下,使其正常工作的机会通常为零;解决这个问题的唯一明智的方法是预防(找到一种避免处理复杂多边形的方法)。

答案 1 :(得分:0)

首先构造多边形的planar straight-line graph(PSLG)。换句话说,将多边形视为一束线段,并在每个相交处将线段拆分。在一个极端的情况下,两个或多个线段可以在一个不重要的线段中重叠,而不是一个点。在PSLG中,相交线段应该是单个,独立的线段,但是我们还需要知道有多少线段的线段重叠。因此,这个退化的多边形(A-B-C-D-E-F-G-A

A-C-B-D
|    /
|   /
G--E---F

变成

   3
*-*-*-*
|    /
|   /
*--*---* ,
     2

忽略所有标有1的标签。

下一步是计算此PSLG的组合嵌入。这意味着我们在顶点上循环,以逆时针顺序按角度对每个顶点的入射边缘进行排序。以标准的计算几何方式,我们可以使用有符号区域来获得不涉及trig的比较器。

现在,我们有一个像这样的数据结构。

   3
t-u-v-w
|    /
|   /
x--y---z ,
     2

t: t-u, t-x, t-y
u: u-v (3), u-t
v: v-w, v-u (3)
w: w-v, w-y
x: x-y, x-t
y: y-z (2), y-w, y-x
z: z-y (2)

我们在定向边缘(此后为 darts )上得到了一个排列,其中每个都指向列表中的下一个(如果需要,可以环绕)。

t-u -> t-x
t-x -> t-u
u-v (3) -> u-t
u-t -> u-v (3)
v-w -> v-u (3)
v-u (3) -> v-w
w-v -> w-y
w-y -> w-v
x-y -> x-t
x-t -> x-y
y-z (2) -> y-w
y-w -> y-x
y-x -> y-z (2)
z-y (2) -> z-y (2)

我们通过构造一个新的排列(每个飞镖指向其当前分配的相反方向)来计算该嵌入的对偶。

t-u -> x-t
x-t -> y-x
y-x -> z-y (2)
z-y (2) -> y-z (2)
y-z (2) -> w-y
w-y -> v-w
v-w -> u-v (3)
u-v (3) -> t-u

t-x -> u-t
u-t -> v-u (3)
v-u (3) -> w-v
w-v -> y-w
y-w -> x-y
x-y -> t-x

现在,我将排列分为周期。这些循环是PSLG的面(按顺时针顺序在多边形内部,按逆时针顺序无限远)。使用signed area test查找无限的面孔。

返回到图形表示形式,对无限面处的根面进行深度优先搜索,将每个面标记为奇数(如果边上的数字之和为奇数)或偶数。奇数周期的集合是您要寻找的结果。

实际上,既然我已经写出了整个答案,最好只删除一开始的偶数多样性片段,以将相邻的多边形混在一起。这可能会导致多个无穷大的面孔,但检测方法仍然有效。

相关问题