首先构建多边形的 平面直线图 (PSLG)。换句话说,将多边形视为一堆线段,在每个交点处分割线段。存在一个特殊情况,即两个或多个线段可以在一个非平凡的线段中重叠,而不是在一个点上。在 PSLG 中,交点线段应该是单独的分离线段,但我们还需要知道有多少条线段与它重叠。因此,这是一个退化的多边形 (A-B-C-D-E-F-G-A
)
A-C-B-D
| /
| /
G--E---F
转化成
3
*-*-*-*
| /
| /
*--*---* ,
2
省略所有标签上的
1
。
接下来的步骤是计算此PSLG的组合嵌入。这意味着我们遍历顶点,按逆时针顺序按角度对每个顶点的入射边进行排序。在标准计算几何中,我们可以使用有符号面积得到一个比较器,它不涉及三角函数。
现在,我们有了以下数据结构。
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)
我们得到一个定向边(以下简称箭头)的排列,其中每个箭头指向列表中的下一个箭头(如果需要则循环)。
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的面(顺时针顺序内部多边形和逆时针顺序无限面)。使用有向面积测试来找到无限面。
回到图形表示,对以无限面为根的面进行深度优先搜索,标记每个面为奇数(如果边上数字的总和为奇数)或偶数。奇数循环的集合就是你要寻找的结果。
实际上,既然我已经写出了整个答案,最好只需删除开始的偶数重复段,将相邻的多边形压缩在一起。这可能会导致多个无限面,但检测方法仍然有效。