【学习笔记:计算几何基础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)

    以线段为例
    1502976-20181006204725223-1786868076.png
    朴素:对于所有区间搜索判定O(n^2)

    改进

  • 染色
    对于所有的线段,左端点标1,右端点标2
  • 排序
    左端点第一关键字,右端点第二关键字
  • 扫描
    依次检查相邻的端点,检查他们的Patterns
    结论:如果无交,那么他们的Patterns 一定是1 2 相间 反之不然
    所以时间复杂度降为O(nlogn)

    Segment Intersection Detection (SID)

    朴素枚举 O(n^2)
    关于判断
    ToLeft Text
    4次判断,如果对于两条线段每次的两个结果都为在异侧则相交

    更优的算法(BO算法)

    先了解几个结论

    Separebility

    如果线段在垂直方向上可分开,那么一定不可能相交
    1502976-20181006211505350-1606495633.png
    所以我们尝试在筛选完后,进行比对
    更近一步,如果两条线段是相交的,当且仅当他们与某一条垂直线相交
    1502976-20181006211654113-592749301.png
    所以我们可以采用类似扫描线的想法,我们当前考虑的仅仅是与当前线相交的
    需要注意的是显然我们不可能让扫描线都扫过全部的数,事实上,我们只用处理很少的位置,即只处理端点处和与线段有交点的时刻。
    1502976-20181006212530887-1474635507.png
    如图,当扫描线处于t时刻是,我们仅仅考虑图中的蓝线,同时,我们可以按高度对他们依次遍历。对于高度,我们定义交点高度越高,那么线段越高。
    很显然的是,这几个点的序列是动态的 ,所以我们需要考虑如何去更新
    而这样的变化仅仅发生在三种状况下
  1. 左端点处增加
  2. 右端点处减少
  3. 交点处高度变化
    1502976-20181006213105440-1159220327.png
    如图,在L,X,R位置时,序列会发生变化 ,对此将这三种情况统称为事件。

    数据结构

    状态结构

    用于组织垂直方向上的线段的顺序

    事件队列

    用于水平方向的顺序,按优先级储存

    维护

    1502976-20181007063938799-1210741736.png
    当扫描线处于这样的位置时,应当对结构进行insert操作,同时,对于这个线段,交点可能增加在它在状态结构中的直接前驱和直接后继,即图中与e相交的两条
    1502976-20181007064435059-1309215789.png
    当然也存在这样的情况,那么我们需要对结构进行Delete操作,同时我们更新他的直接前驱与直接后继变为相邻并检查端点
    1502976-20181007064828246-1662175842.png
    第三种事件,更新线段的对应高度,交完相交两个线段的高度,同时更改线段的临近关系同时检查是否产生新的交点

    特例

    1502976-20181007065425580-1480088644.png
  • 垂直的线段
  • 平行(共线)的线段(包括部分重合交于无穷多个点)
  • 共点的线段
    对于这些退化的情况在算法中暂时不考虑,但实际操作上需要进行特殊的处理

    事件队列的实现

    1502976-20181007070110970-2146803775.png
    很显然的是这里需要用优先队列去维护

    事件及维护

    1502976-20181007070621815-1257357507.png
    初始化,将所有线段的左右端点放入队列中。
    1502976-20181007070839052-1132483664.png
    更新,对队列插入仅存在产生新的交点(交点可能与某个左右端点重合)
    那么整个过程就是每次取出头事件,检查完后将新的端点更新

    状态结构的实现

    采用(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都能划分为两条单调的多边形链。 即链上的点的高度延着链递增或递减
    1502976-20181007085412599-669303566.png
  • 增强链
    对两条链增设两条射线
    1502976-20181007085646421-932207560.png
    那么我们能将体的相交转换为链的相交
  1. Criterion
    如果两个CP不交,那么他们的相对链不交,即图中蓝链与蓝链不交或者红链与红链不交 换句话说,如果两个CP相交,则必然蓝红链同时相交。
    1502976-20181007090026581-1071052217.png
    那么我们如何判定半无穷链相交
  2. Judge
    二分查找

    伪代码

    判定(多边形P左链,多边形Q右链)
    如果(P或Q只剩下一条边) 直接判断
    否则 定义两个mid为两条链的mid边
    分两中情况:
    • 两条mid边相交
    • 减除不能相交的一半

1502976-20181007091503297-1617514674.png
相交的情况
1502976-20181007091615752-555874087.png
如果是上三角位置关系,那么下半部分无用。
1502976-20181007091827341-1530391520.png
如果是下三角的位置关系,那么下半部分无用。

复杂度

每次判定至少会有一条链的一半去除
那么可以的出递推式
T(N) = T(3N/4)+O(1)
T(1)=O(1)
故为O(logn)

构造问题

即将CP的交部分构造出来

Edge Chasing 算法

基本思想,将两个CP的不交的部分去掉,即减除月牙部分
1502976-20181007092932807-421403097.png

过程
遍历边 
查探是p上的边上升还是q上的边上升 

1502976-20181007093549666-36067427.png
时间复杂度O(n+m)

转载于:https://www.cnblogs.com/PiCaHor/p/9748597.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值