基础计算几何

2-D

\(|(x,y)|=\sqrt{x^2+y^2}\)

夹角

\(<\vec a,\vec b>\)表示从\(\vec a\)逆时针旋转到\(\vec b\)的角度。

点积

\((ax,ay)\cdot(bx,by)=ax*bx+ay*by\)
\(\vec a\cdot\vec b=|\vec a||\vec b|\cos<\vec a,\vec b>\)

叉积

\((ax,ay)\times(bx,by)=ax*by-ay*bx\)
\(\vec a\times\vec b=|\vec a||\vec b|\sin<\vec a,\vec b>\)

极角

\((x,y)\)的极角\(\varphi=<(1,0),(x,y)>=\operatorname{arctan}\frac yx\)

面积

\(\vec a\)\(\vec b\)所成平行四边形的面积为\(|\vec a\times\vec b|\)

旋转

\((x,y)\)逆时针旋转\(\theta\)得到\((x\cos\theta-y\sin\theta,y\cos\theta+x\sin\theta)\)

线段相交

\(\operatorname{seg}(\vec{a_1},\vec{a_2}),\operatorname{seg}(\vec{b_1},\vec{b_2})\)相交\(\Leftrightarrow\)\(((\vec{b_1}-\vec{a_1})\times(\vec{b_1}-\vec{a_2}))((\vec{b_2}-\vec{a_1})\times(\vec{b_2}-\vec{a_2}))\le0\wedge((\vec{a_1}-\vec{b_1})\times(\vec{a_1}-\vec{b_2}))((\vec{a_2}-\vec{b_1})\times(\vec{a_2}-\vec{b_2}))\le0\)

直线交点

先用叉积判断平行,然后利用定比分点计算。
\(\operatorname{line}(\vec{a_1},\vec{a_2}),\operatorname{line}(\vec{b_1},\vec{b_2})\)的交点为\(\vec{a_1}+\frac{(\vec{b_2}-\vec{b_1})\times(\vec{b_1}-\vec{a_1})}{(\vec{b_2}-\vec{b_1})\times(\vec{a_2}-\vec{a_1})}(\vec{a_2}-\vec{a_1})\)

凸包

给定点集\(X\),所有包含\(X\)的凸多边形的交称作\(X\)的凸包。
默认凸包有一原点为\((0,0)\)

Graham扫描法

选取横坐标最小的点作为原点,并将其它的点按与原点连成的向量按极角排序(极角相同的按模长升序排序)。
接下来分别求出上凸包与下凸包,以下凸包为例。
我们用栈维护凸包,设当前点为\(now\),栈顶和第二个点分别为\(A,B\),若\(A\)在直线\((B,now)\)的上方,那么将\(A\)弹出。
求上凸包的过程类似,将“上方”改为“下方”即可。

Mincowsky和

\(X,Y\)两个点集的Mincowsky和\(X+Y=\{x+y|x\in X,y\in Y\}\)

可以看到\(X+Y\)的边是由\(X,Y\)的边构成的。
因此我们可以把\(X,Y\)的边归并排序,然后为了处理三点共线的情况再用Graham扫描法求一遍凸包就好了。

判断点是否在凸包内

先判断与边界的关系,然后找到与其极角相邻的两点进行判断。

多边形

判断点是否在多边形内

从该点引一射线,若与多边形相交偶数次则在凸包内。

内核

一个多边形的内核是所有满足与多边形内任意一点之间的连线不跨过多边形的边界的点构成的点集。
很显然,一个多边形的内核是所有边所在直线的多边形内一侧的半平面的交。

面积

以原点为中心三角剖分,然后直接叉积求即可。

半平面交

半平面交的结果可能是无穷平面、多边形、直线、射线、线段、点、空集等。
我们给每条直线定向,并默认合法半平面为直线逆时针方向的半平面。
求半平面分为以下几步:
\(1.\)将所有直线按极角排序,极角相同的直线仅保留最左侧的。
\(2.\)用双端队列维护最后半平面交中的线段。
\(3.\)按照排序后的顺序遍历所有直线,每次加入一条新的线段就弹出在该直线右侧的队头、队尾的线段。

最小圆覆盖

求面积最小的覆盖\(\vec{a_1},\cdots,\vec{a_n}\)的圆。

\(O(n^3)\)做法:
考虑如何从\(\vec{a_1},\cdots,\vec{a_{i-1}}\)的最小圆覆盖\(\bigcirc(O,R)\)推到\(\vec{a_1},\cdots,\vec{a_i}\)的最小圆覆盖\(\bigcirc'(O',R')\)
如果\(\vec{a_i}\in\bigcirc\),那么\(\bigcirc'=\bigcirc\)
如果\(\vec{a_i}\notin\bigcirc\),那么先令\(\bigcirc'=((0,0),0)\)
在这种情况下继续枚举\(j\in[1,i)\),如果\(\vec{a_j}\notin \bigcirc'\),那么就将\(\bigcirc'\)变成以\(\operatorname{seg}(\vec{a_i},\vec{a_j})\)为直径的圆。
在这种情况下继续枚举\(k\in[1,j)\),如果\(\vec{a_k}\notin\bigcirc'\),那么就将\(\bigcirc'\)变成经过\(\vec{a_i},\vec{a_j},\vec{a_k}\)的圆。
期望\(O(n)\)做法:最开始random_shuffle点序列,然后按照上面的方法做。

旋转卡壳

对踵点对

若两点在多边形的两条平行切线上,则我们称该两点为对踵点对。
我们认为多边形边界与它的切线的交集可以为多边形的顶点或边,因此有“点-点”、“点-边”、“边-边”三种类型的对踵点对。
旋转卡壳是在\(O(n)\)内求出凸多边形所有对踵点对的算法。

以“点-边”对踵点对为例。
我们逆时针枚举多边形的每条边,与它对踵的点显然也是逆时针运动的。
那么用一个单调指针维护即可。
“点-点”对踵点对和“边-边”对踵点对同理。

利用对踵点对我们可以计算直径、宽、最小面积外接矩形、最小周长外接矩形等属性。
同时还可以进行环形三角剖分、螺旋三角剖分、合并凸包等算法。

Descartes定理

若平面上四个半径分别为\(r_1,r_2,r_3,r_4\)的圆相切于六点,则其半径满足以下结论:
\(1.\)若四圆两两外切,则\((\frac1{r_1}+\frac1{r_2}+\frac1{r_3}+\frac1{r_4})^2=2(\frac1{r_1^2}+\frac1{r_2^2}+\frac1{r_3^2}+\frac1{r_4^2})\)
\(2.\)若半径为\(r_1,r_2,r_3\)内切于半径为\(r_4\)的圆中,则\((\frac1{r_1}+\frac1{r_2}+\frac1{r_3}-\frac1{r_4})^2=2(\frac1{r_1^2}+\frac1{r_2^2}+\frac1{r_3^2}+\frac1{r_4^2})\)

Pick定理

若一个顶点都是整点的多边形满足\(2S=2a+b-2\),其中\(a\)是多边形内部的整点数,\(b\)是多边形边界上的整点数。

3-D

\(|(x,y,z)|=\sqrt{x^2+y^2+z^2}\)

夹角

\(<\vec a,\vec b>\)表示从\(\vec a\)逆时针旋转到\(\vec b\)的角度。

点积

\((ax,ay,az)\cdot(bx,by,bz)=ax*bx+ay*by+az*bz\)
\(\vec a\cdot\vec b=|\vec a||\vec b|\cos<\vec a,\vec b>\)

叉积

\((ax,ay,az)\times(bx,by,bz)|=(ay*bz-az*by,az*bx-ax*bz,ax*by-ay*bx)\)
\(|\vec a\times\vec b|=|\vec a||\vec b|\sin<\vec a,\vec b>\)
\(\vec a\times\vec b\perp \operatorname{flat}(\vec a,\vec b)\)
\(\vec a\times\vec b\)的方向遵循右手定则:将食指由\(\vec a\)的方向转向\(\vec b\)的方向,大拇指的朝向就是\(\vec a\times\vec b\)的方向。

混合积

\([\vec a,\vec b,\vec c]=(\vec a\times\vec b)\cdot\vec c\)
\(\vec a,\vec b,\vec c\)所成六面体的体积为\(|[\vec a,\vec b,\vec c]|\)

Euler定理

\(V-E+F=2\)

posted @ 2020-02-19 20:01  Shiina_Mashiro  阅读(300)  评论(0编辑  收藏  举报