走上计算几何的漫漫不归路(雾)。
基本概念
点积
令 ,则它们的点积等于 。
应用:两向量垂直,其点积为 。
叉积
令 ,则它们的点积等于 。
应用:叉积的几何意义为两向量 共起点时所构成平行四边形的面积。叉积 ,两向量平行;叉积 ,向量 在向量 的顺时针方向;叉积 ,向量 在向量 的逆时针方向。
旋转向量
将向量 旋转 $\theta $ 角度后,坐标为 。
证明:令向量 与 轴夹角为 $\alpha $ ,则旋转之后夹角为 $\alpha + \theta $ 。利用 与 及和角公式可得证。
多边形的面积
若已知一个简单多边形的顶点按逆时针顺序依次为 ,则其面积为:
极角排序
在平面上取一定点 ,从 引一条水平射线 ,规定方向自左至右,再选定一个长度单位并规定角旋转的正方向,通常取逆时针方向,这样就构成了一个极坐标系。点 叫作极点,射线 叫作极轴。
常见的极角排序方法有四种,这里给出利用叉积进行排序的代码(以原点为极点)。
1 | struct node{double x,y;}; |
凸包
Graham扫描法
一个点集的凸包就是能包围给定点的最小的凸多边形。
构造出点集的凸包的方式为:以点集中纵坐标最小的点为极点(纵坐标相同则横坐标最小,易得这个点一定在凸包上),其他点做极角排序,然后按照极角序扫描,加入一个点时利用叉积判断之前的点是否合法即可。
相关应用
查询一个点是否位于凸包内部:按照极角序二分出在哪两个点之间,判断一下是否在该线段内侧。
一条斜率为 的直线从正无穷远处向下平移,碰到的第一个点:在凸包上二分斜率。
支持插入操作的动态凸包:离线写法可以使用 cdq 分治,在线写法可以利用平衡树来维护。
坐标范围为 的整点凸包的点数上界: 。
旋转卡壳
对踵点
如果过凸包上的两个点可以画一对平行直线,使凸包上的所有点都夹在两条平行线之间或落在平行线上,那么这两个点叫做一对对踵点。使用旋转卡壳算法可以求出凸多边形的所有对踵点。
算法原理
我们只需要维护两条平行直线中至少有一条卡住了一条边的情况,即可求出所有的对踵点。
枚举凸包上的每一条边,当它被一条直线卡住时,另一条直线一定卡住了离该边最远的点,且该点与该边的两个端点构成了两对对踵点。因为凸包上的点距离固定边的距离是单峰的,改变枚举边时只需要直接移动到对应点即可,且移动过程中经过的点都能与这两条相邻边的交点构成对踵点。时间复杂度 。
应用
详见博客 《计算几何之旋转卡壳算法》
半平面交
基本概念
半平面是指二维平面上一条直线的一侧的所有空间。通常使用点对 表示在向量 左侧的半平面。
多个半平面的交是空集或非空凸集。
构造方法
首先对所有的半平面进行极角排序,对于极角相同的半平面有选择性地保留,并在双端队列中加入最开始的两个半平面。
考虑加入一个新的半平面:当队头的两个半平面的交点在该半平面外,删除队头的半平面;队尾同理;然后将新的半平面加入队尾。
添加完所有的半平面后,删除两端多余的半平面的方法为:若队头的两个半平面的交点在队尾半平面外,删除队头的半平面;队尾同理。
判断交点在半平面外可以利用叉积解决。
参考资料
- 《计算几何选讲》,dwjshift
- 极角 - 百度百科
- 半平面交 - 百度百科