【学习笔记:计算几何基础4】 Geometric Intersection

Ahead

10.6.2018-10.7.2018
新的章节,从凸包到几何求交

定义

在一组几何物体中找到公共部分
问题主要分4类

  1. 判断问题(Determine) 即判定是否有交
  2. 计数问题(Count) 计算有多少交点
  3. 枚举问题(Enumerate) 枚举交点是那些(在哪里)
  4. 构造问题(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时刻是,我们仅仅考虑图中的蓝线,同时,我们可以按高度对他们依次遍历。对于高度,我们定义交点高度越高,那么线段越高。
很显然的是,这几个点的序列是动态的 ,所以我们需要考虑如何去更新
而这样的变化仅仅发生在三种状况下

  1. 左端点处增加
  2. 右端点处减少
  3. 交点处高度变化

    如图,在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算法

  1. Monotone Partitioning
  • 单调划分。
    任何一个CP都能划分为两条单调的多边形链。 即链上的点的高度延着链递增或递减
  • 增强链
    对两条链增设两条射线

    那么我们能将体的相交转换为链的相交
  1. Criterion
    如果两个CP不交,那么他们的相对链不交,即图中蓝链与蓝链不交或者红链与红链不交 换句话说,如果两个CP相交,则必然蓝红链同时相交。

    那么我们如何判定半无穷链相交
  2. 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)

posted @ 2018-10-06 21:35  PiCaHor  阅读(651)  评论(0编辑  收藏  举报