计算几何基础——operator_

前言

东西好多啊 ⋯ \cdots 还好都不算难

向量的基本表示与运算

向量的定义:可以理解成只有方向和长度,没有位置的量(亦称矢量)

向量的表示:在平面几何中表示为 A B → \overrightarrow{AB} AB ,但在程序中一般用平面直角坐标系表示法,即 向量 P ( x 1 , y 1 ) P(x_1,y_1) P(x1,y1)代表从原点指向 P P P的向量。用这种定义,显然从 A ( x a , y a ) A(x_a,y_a) A(xa,ya)指向 B ( x b , y b ) B(x_b,y_b) B(xb,yb)的向量等价于向量 Q ( x b − x a , y b − y a ) Q(x_b-x_a,y_b-y_a) Q(xbxa,ybya)

P S . PS. PS.零向量确实存在,即 0 → \overrightarrow{0} 0 ,大小为 0 0 0,方向为任意方向

向量的加减:向量的加减    ⟺    \iff 坐标的加减,即 P ( x 1 , y 1 ) ± Q ( x 2 , y 2 ) = R ( x 1 ± x 2 , y 1 ± y 2 ) P(x_1,y_1)\pm Q(x_2,y_2)=R(x_1\pm x_2,y_1\pm y_2) P(x1,y1)±Q(x2,y2)=R(x1±x2,y1±y2)显然向量的加减满足交换律、结合律。

向量的叉乘: P ( x 1 , y 1 ) × Q ( x 2 , y 2 ) = x 1 y 2 − x 2 y 1 P(x_1,y_1)\times Q(x_2,y_2)=x_1y_2-x_2y_1 P(x1,y1)×Q(x2,y2)=x1y2x2y1叉乘的核心用途为判断位置关系,即若 P × Q < 0 P\times Q<0 P×Q<0 P P P Q Q Q逆时针方向,反之若 P × Q 》 0 P\times Q》0 P×Q0 P P P Q Q Q顺时针方向,若 P × Q = 0 P\times Q=0 P×Q=0 P , Q P,Q P,Q共线(但不知道是否同向)。显然向量的叉乘结果为一个数且不满足交换律。

接下来依次讨论两个东西的位置关系(点、线段、矩形、圆、多边形 ⋯ \cdots

点与矩形

点为 P ( x 0 , y 0 ) P(x_0,y_0) P(x0,y0),矩形左下顶点与右上顶点分别为 A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A(x_1,y_1),B(x_2,y_2) A(x1,y1),B(x2,y2)

点在矩形内: x 1 ≤ x 0 ≤ x 2 x_1\le x_0\le x_2 x1x0x2 y 1 ≤ y 0 ≤ y 2 y_1\le y_0\le y_2 y1y0y2

复杂度 O ( 1 ) O(1) O(1)

点与线段

点为 P ( x 0 , y 0 ) P(x_0,y_0) P(x0,y0),线段两端点分别为 A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A(x_1,y_1),B(x_2,y_2) A(x1,y1),B(x2,y2)

点在线段上: A P → × A B → = 0 \overrightarrow{AP}\times \overrightarrow{AB}=0 AP ×AB =0 x 1 ≤ x 0 ≤ x 2 x_1\le x_0\le x_2 x1x0x2 y 1 ≤ y 0 ≤ y 2 y_1\le y_0\le y_2 y1y0y2

复杂度 O ( 1 ) O(1) O(1)

线段与线段

两条线段两端点分别为 A ( x 1 , y 1 ) A(x_1,y_1) A(x1,y1) B ( x 2 , y 2 ) B(x_2,y_2) B(x2,y2) M ( x 3 , y 3 ) M(x_3,y_3) M(x3,y3) N ( x 4 , y 4 ) N(x_4,y_4) N(x4,y4)

线段与线段相交: ( A M → × A B → ) ∗ ( A N → × A B → ) ≤ 0 (\overrightarrow{AM}\times \overrightarrow{AB})*(\overrightarrow{AN}\times \overrightarrow{AB})\le0 (AM ×AB )(AN ×AB )0 ( M A → × M N → ) ∗ ( M B → × M N → ) ≤ 0 (\overrightarrow{MA}\times \overrightarrow{MN})*(\overrightarrow{MB}\times \overrightarrow{MN})\le0 (MA ×MN )(MB ×MN )0

复杂度 O ( 1 ) O(1) O(1)

注意特判平行和首尾相接

射线、直线均可类比求得(更简单)

点与多边形

点为 P ( x 0 , y 0 ) P(x_0,y_0) P(x0,y0),多边形有 n n n条边

点在多边形内:过点 P P P引一条平行于坐标轴的射线,枚举每条边求交点数,交点数之和为奇数则在多边形内,反之不在。

复杂度 O ( n ) O(n) O(n)

注意特判平行和交于顶点

线段与多边形

线段两端点分别为 A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A(x_1,y_1),B(x_2,y_2) A(x1,y1),B(x2,y2),多边形有 n n n条边

线段在多边形内: A A A在多边形内且 B B B在多边形内且 A B AB AB与多边形无内交点(枚举求得)

复杂度 O ( n ) O(n) O(n)

注意特判内交与平行

P S . PS. PS.老师有复杂度 O ( n l o g n ) O(nlogn) O(nlogn)但不用特判的做法,不过个人感觉没必要。

多边形与多边形

这个反而简单

两个多边形分别有 n n n m m m条边

多边形在多边形内:依次判断每条边是否在另一多边形内即可

复杂度 O ( n m ) O(nm) O(nm)

点与圆

点为 P ( x 1 , y 1 ) P(x_1,y_1) P(x1,y1),圆心为 O ( x 0 , y 0 ) O(x_0,y_0) O(x0,y0),半径为 r r r

点在圆内: P O < r PO<r PO<r,若想避免精度误差就用 ( x 0 − x 1 ) 2 + ( y 0 − y 1 ) 2 < r 2 (x_0-x_1)^2+(y_0-y_1)^2<r^2 (x0x1)2+(y0y1)2<r2

复杂度 O ( 1 ) O(1) O(1)

线段与圆

圆是凸的

线段两端点分别为 A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A(x_1,y_1),B(x_2,y_2) A(x1,y1),B(x2,y2),圆心为 O ( x 0 , y 0 ) O(x_0,y_0) O(x0,y0),半径为 r r r

线段在圆内: ( x 0 − x 1 ) 2 + ( y 0 − y 1 ) 2 < r 2 (x_0-x_1)^2+(y_0-y_1)^2<r^2 (x0x1)2+(y0y1)2<r2 ( x 0 − x 2 ) 2 + ( y 0 − y 2 ) 2 < r 2 (x_0-x_2)^2+(y_0-y_2)^2<r^2 (x0x2)2+(y0y2)2<r2(即端点都在圆内)

复杂度 O ( 1 ) O(1) O(1)

多边形与圆

圆是凸的

多边形有 n n n条边,圆心为 O ( x 0 , y 0 ) O(x_0,y_0) O(x0,y0),半径为 r r r

多边形在圆内:等价于顶点都在圆内(枚举判断)

复杂度 O ( n ) O(n) O(n)

圆在多边形内:避免不了精度误差了最暴力的求 O O O到多边形每条边的端点的距离、用"垂直的一次函数斜率之积为 − 1 -1 1"求解 O O O到该边的垂直距离(如果垂足在线段上的话),求最小值与 r r r比较

复杂度 O ( n ) O(n) O(n)

细节很多

圆与圆

圆心分别为 O 1 ( x 1 , y 1 ) O_1(x_1,y_1) O1(x1,y1) O 2 ( x 2 , y 2 ) O_2(x_2,y_2) O2(x2,y2),半径为 r 1 r_1 r1 r 2 r_2 r2

圆在圆内: O 1 O 2 < r 1 − r 2 O_1O_2<r_1-r_2 O1O2<r1r2

圆与圆相交: r 1 − r 2 < O 1 O 2 < r 1 + r 2 r_1-r_2<O_1O_2<r_1+r_2 r1r2<O1O2<r1+r2

圆与圆相离: O 1 O 2 > r 1 + r 2 O_1O_2>r_1+r_2 O1O2>r1+r2

复杂度 O ( 1 ) O(1) O(1)

特判边界

凸包

定义:形象的将,在木板上有n个钉子,拿根牛皮筋从无限远处开始收缩,问最后成了什么样(可能问周长或面积)

这里只讲单调链算法

对所有点进行 x − y x-y xy从小到大排序(以 x x x为第一关键字,以 y y y为第二关键字)

从最左下点开始维护一个栈,按顺序扫描,当碰到一个新的点时,判断这个点是否在栈顶 2 2 2个点形成的线段的顺时针方向,若是,则弹出栈顶,加入该点,否则不加。

做到最后一个点时,栈中的点就是该凸包的下凸壳,再反向搜一遍求出上凸壳即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值