半平面交
简介
博客背景
笔者在学习半平面交时,网上找入门博客资源甚少,且大部分难以理解,故在稍稍入门了半平面交后,写此博客,希望能对大家有所帮助。若有错误,麻烦指出。
半平面交是什么?
我们知道一条直线可以把平面分为两部分,其中一半的平面就叫半平面。
那半平面交,就是多个半平面的相交部分。我们在学习线性规划时就有用过。
半平面交有什么用?
1.求解一个区域,可以看到给定图形的各个角落。(多边形的核)
2.求可以放进多边形的圆的最大半径。
求解半平面交的步骤(S&I算法 O(nlogn))
我们试着来解决 “求解一个区域,可以看到给定图形的各个角落。”
为了叙述方便,我们把这个区域叫做多边形的核。
1.选取一个正方向。(一般为逆时针)
我们用这个一个不规则图形举例子。
首先我们选逆时针方向做为有向线段。
这样选取的好处是,保证核在有向线段的左边。
2.把有向线段通过极角排序(与 x x x 轴的夹角)(-180°,180°]
排序结果如下所示。
按照极角排序的原因是写代码方便,排序之后的线段是有序的,可以在双端队列里进行操作。(下面会再解释)。
3.按顺序遍历每条线段,取左边区域,删右边区域
我们用这个 S&I 算法求解半平面交时,用的是删减法,首先我们假设全部平面都是半平面交,然后不断加入直线,不断删去右边区域,保留左边区域。最后剩下的区域就是需要求的半平面交。
1.全部平面都是半平面交。

2.加入第一条直线,保留左边区域,删除右边区域。

3.加入第二条线段,保留左边区域,删除右边区域。

4.依次加入3 - 10线段,保留左边区域,删除右边区域。

5.加入最后一条线段,保留左边区域,删除右边区域。

6.剩下的蓝色部分,就是多边形的和,也就是所有直线的半平面交,在蓝色区域的任何一点,都可以看到多边形的每一个角落。

7.这时我们得到的是围成这个蓝色区域的直线集合。
L = { 2 , 5 , 7 , 9 , 11 } L = \{2,5,7,9,11\} L={ 2,5,7,9,11} ,如果至少有三条边,就说明该多边形有核(三条以上时,核为全部直线围成的凸包。)如果要求面积,我们可以将直线的交点求出来,然后再用叉积求凸包面积。
4.如果题目要求求面积。
我们可以发现求出来的直线的集合是有序的 L = { 2 , 5 , 7 , 9 , 11 } L = \{2,5,7,9,11\} L={ 2,5,7,9,11},这些直线刚好是逆时针围着这个半平面交。(这就是按极角排序的好处)。如果要求面积,我们可以把所有 L [ i ] L[i] L[i] 和 L [ i + 1 ] L[i + 1] L[i+1] 的交点求出来,然后用叉乘求凸包面积。
5.总结
总体而言,求半平面交其实就是维护线段的集合 L L L,遍历每一条线段,判断这条线段加入后对于半平面交的影响,然后在集合 L L L 中剔除掉对半平面交没有决定作用的边,留下起决定作用的边。即最终目的是维护半平面交的线段集合 L L L。
6.算法优化
1.同极角时,排序后可以去掉右边的线段,保留左边的线段。
例如上述步骤 3-3 时,加入第二条线段。不难发现,当①号线段和②号线段的极角相同时,①号线段没有意义。因为①号线段在②号线段右边。因此在排序后,可以去掉没有意义的线段,即保留极角相同的情况下最