一点点计算几何:向量的入门

学好了数学,你就会成为根神!数学乃万物之根,掌握了数学就掌握了一切!
定义
首先介绍一下点:
点可以用二维坐标 Point
存储。
1 | struct Point{ |
有大小并且有方向的量叫向量。我们可以把他看作连接了两个点。
同时,为了方便,我们可以记录一个坐标,就相当于是从
如图,一个从点
于是为了方便写代码,我们可以执行这个操作:
1 | typedef Point Vector; |
四则运算
- 加法运算
点加点显然是没有意义的。而向量加向量是有意义的。就相当于是把后一个向量的起点给放在前一个向量的终点上,然后求后一个向量的终点的坐标。
例如此图,
那么就相当于是把两个向量的横坐标加起来当作新的横坐标,两个向量的纵坐标当作新的纵坐标。
1 | Vector operator + (const Vector &a, const Vector &b){ |
- 减法运算
几何意义上的向量的减法运算就是:
如果你要求
代数意义上,
1 | Vector operator - (const Vector &a, const Vector &b){ |
- 数乘运算
一个向量乘以一个数
1 | Vector operator * (const Vector &a, const int &b){ |
- 除法运算
一个向量除以一个数 double
或 long double
等等)
1 | Vector operator / (const Vector &a, const int &b){ |
点积与叉积
点积和叉积都是向量乘以向量,但是它们不同。这两个名字其实是根据两个不同的 “乘法符号” 命名的,点积就是
点积
点积的结果是一个数值。运算是这样的:
如图,
这个夹角
而有一种更简单的算法:
考虑证明:
根据这个东西我们可以看出来点积其实是有交换律的。
于是我们可以得出一些性质:
- 若
,那么 与 的夹角为锐角。 - 若
,那么 与 的夹角为钝角。 - 若
,那么 与 的夹角为直角。
(其实看
1 | int Dot(Point u, Point v){ |
点积的应用
最直观地、可以求两个向量的夹角。
1 | double Len(Vector a){ |
叉积
叉积的结果是也一个数值。运算是这样的:
和上面的点积形式比较像,就是把
但是注意:这里的
所以,叉积有正有负。即:
- 当
在 的逆时针方向时(左侧),那么 。 当
在 的顺时针方向时(右侧),那么 。 当
和 的方向相同或相反时(共线),那么 。
这个也可以从
而叉积也有一个很好算的神奇公式:
所以可以看出,叉积没有交换律。叉积是有顺序的。
他的几何意义:以向量
1 | int Cross(Point u, Point v){ |
直线
众所周知,直线可以用以下几个方法表示:
- 用直线上的两个点的坐标表示,因为两点确定一条直线
/ - 根据一个点和倾斜角确定
- 点向式:
: 为一个点, 是一个向量。
1 | struct Line{ |
叉积的应用
- 点和直线的位置关系
判断点
这个可以有两种算法:
- 构造向量
和向量 ,然后用叉积的正负来判断方向。
1 | int Relation(Point p, Line l){ |
- 构造向量
,求 ,然后用叉积的正负判断方向。个人觉得这种方法更加直观。
1 | int Relation(Point p, Line l){ |
例题:
神秘大三角
Tips
在向量运算的过程中,因为用的是 double
类型,所以判断相不相等的时候肯定是会有一些误差的。我们要规避掉。我们可以设置一个极小值
可读性最高的方法是重载运算符。这里使用了重新写一个函数的方式。
1 |
|
于是入门就先到这里,我们来讲二维凸包。(后面可能会在入门里面再添加内容)
二维凸包的定义
二维凸包就相当于,通俗的讲,你在平面上有一些大头针,你有一个橡皮筋,你用一个橡皮筋把所有的这些大头针包在里面,那么这个橡皮筋的形状就可以粗略看作是这些点的凸包的形状。
上图中灰色的一个凸多边形就是这些蓝色点的凸包。它包住了所有的蓝点。
我们来介绍一个
Andrew 算法求二维凸包
我们首先给这些点排序:按照
然后我们选定最左边的点(也就是
我们将我们遍历过的所有点压进一个栈里面,当遍历到一个新的点的时候,判断他和栈顶的两个点的位置关系,然后来判断删不删。我们依然来举例说明:
首先栈中不足
这个时候,第三个点来了,我们让他和栈顶点和次栈顶点判断一下位置关系:
具体的操作是,让 栈顶的点 和 新点和次栈顶的点连成的直线 判断位置关系。如上图,我们发现栈顶点 pop
一下,然后继续检测。直到符合条件或是栈中的元素小于
注意要持续检测!
另一个例子,插入点
注意:当新点和栈顶点、次栈顶点共线时:
看题目要求。
当所有点都被遍历完了之后,我们看到了一个凸包的雏形:
注:这里的
然后我们就可以开始再从后往前遍历一遍,来找上凸包。
找上凸包的过程其实和找下凸包的过程都是一样的,但是注意一下边界问题。
具体地说,弹出元素的操作只适用于当前栈元素大于
因为你再弹出,你就把下凸包的右端点给弹出去了。
最后,我们得到了一个栈和一个凸包:
但是,我们发现这个凸包的点(即栈)里面有两个左端点。就判一下(设栈中元素个数为
当
于是我们就完美的得到了这个凸包了!
例题:
二维凸包模板
- Title: 一点点计算几何:向量的入门
- Author: 11490DX
- Created at : 2024-12-07 00:00:00
- Updated at : 2025-02-14 13:09:36
- Link: https://11490dx.net/2024/12/07/vector/
- License: This work is licensed under CC BY-NC-SA 4.0.