【学习笔记:计算几何基础4】 Geometric Intersection
Ahead
10.6.2018-10.7.2018
新的章节,从凸包到几何求交
定义
在一组几何物体中找到公共部分
问题主要分4类
- 判断问题(Determine) 即判定是否有交
- 计数问题(Count) 计算有多少交点
- 枚举问题(Enumerate) 枚举交点是那些(在哪里)
- 构造问题(Construct) 几何物体的公共交本身构造出新的几何物体
Element Uniqueness (EU)
元素唯一性判定检测
排序判定(nlogn)
Min-Gap问题
最小空隙问题
同样可以O(nlogn) 排序求解
IEU
元素类型一定是整数
求交算法
判定问题
Interval Intersection Detection(IID)
以线段为例
朴素:对于所有区间搜索判定O(n^2)
改进
- 染色
对于所有的线段,左端点标1,右端点标2 - 排序
左端点第一关键字,右端点第二关键字 - 扫描
依次检查相邻的端点,检查他们的Patterns
结论:如果无交,那么他们的Patterns 一定是1 2 相间 反之不然
所以时间复杂度降为O(nlogn)
Segment Intersection Detection (SID)
朴素枚举 O(n^2)
关于判断
ToLeft Text
4次判断,如果对于两条线段每次的两个结果都为在异侧则相交
更优的算法(BO算法)
先了解几个结论
Separebility
如果线段在垂直方向上可分开,那么一定不可能相交
所以我们尝试在筛选完后,进行比对
更近一步,如果两条线段是相交的,当且仅当他们与某一条垂直线相交
所以我们可以采用类似扫描线的想法,我们当前考虑的仅仅是与当前线相交的
需要注意的是显然我们不可能让扫描线都扫过全部的数,事实上,我们只用处理很少的位置,即只处理端点处和与线段有交点的时刻。
如图,当扫描线处于t时刻是,我们仅仅考虑图中的蓝线,同时,我们可以按高度对他们依次遍历。对于高度,我们定义交点高度越高,那么线段越高。
很显然的是,这几个点的序列是动态的 ,所以我们需要考虑如何去更新
而这样的变化仅仅发生在三种状况下
- 左端点处增加
- 右端点处减少
- 交点处高度变化
如图,在L,X,R位置时,序列会发生变化 ,对此将这三种情况统称为事件。
数据结构
状态结构
用于组织垂直方向上的线段的顺序
事件队列
用于水平方向的顺序,按优先级储存
维护
当扫描线处于这样的位置时,应当对结构进行insert操作,同时,对于这个线段,交点可能增加在它在状态结构中的直接前驱和直接后继,即图中与e相交的两条
当然也存在这样的情况,那么我们需要对结构进行Delete操作,同时我们更新他的直接前驱与直接后继变为相邻并检查端点
第三种事件,更新线段的对应高度,交完相交两个线段的高度,同时更改线段的临近关系同时检查是否产生新的交点
特例
- 垂直的线段
- 平行(共线)的线段(包括部分重合交于无穷多个点)
- 共点的线段
对于这些退化的情况在算法中暂时不考虑,但实际操作上需要进行特殊的处理
事件队列的实现
很显然的是这里需要用优先队列去维护
事件及维护
初始化,将所有线段的左右端点放入队列中。
更新,对队列插入仅存在产生新的交点(交点可能与某个左右端点重合)
那么整个过程就是每次取出头事件,检查完后将新的端点更新
状态结构的实现
采用(BBST)平衡树(AVL,Treap,Splay),操作仅包括增加,删除,交换,查询前驱,查询后继
时间复杂度
最多只用处理2n+I 每次处理的时间是logn 所以总的时间复杂度是O((n+I)logn)
值得注意的是当I 扩大到N^2时,BO算法会比较糟糕,不过,在绝大多数下,这种情况是足够的,如果可以的话,可以加一个自适应调整 。
Convex Polygons Intersection Detection (CPID)
- 区分:分为边界交与内部交
- 约定:如果一个CP被包含于另一个CP中,我们视为相交
Kirkpatrick算法
- Monotone Partitioning
- 单调划分。
任何一个CP都能划分为两条单调的多边形链。 即链上的点的高度延着链递增或递减
- 增强链
对两条链增设两条射线
那么我们能将体的相交转换为链的相交
- Criterion
如果两个CP不交,那么他们的相对链不交,即图中蓝链与蓝链不交或者红链与红链不交 换句话说,如果两个CP相交,则必然蓝红链同时相交。
那么我们如何判定半无穷链相交 - Judge
二分查找
伪代码
判定(多边形P左链,多边形Q右链)
如果(P或Q只剩下一条边) 直接判断
否则 定义两个mid为两条链的mid边
分两中情况:
* 两条mid边相交
* 减除不能相交的一半
相交的情况
如果是上三角位置关系,那么下半部分无用。
如果是下三角的位置关系,那么下半部分无用。
复杂度
每次判定至少会有一条链的一半去除
那么可以的出递推式
T(N) = T(3N/4)+O(1)
T(1)=O(1)
故为O(logn)
构造问题
即将CP的交部分构造出来
Edge Chasing 算法
基本思想,将两个CP的不交的部分去掉,即减除月牙部分
过程
遍历边
查探是p上的边上升还是q上的边上升
时间复杂度O(n+m)