计算几何
-
前置知识:
-
pi = acos(-1)
-
余弦定理:
c
2
=
a
2
+
b
2
?
2
a
b
c
o
s
(
t
)
c^2 = a^2+b^2-2abcos(t)
c2=a2+b2?2abcos(t) -
浮点数的比较。 const double eps = 1e-8;
int sign(double x){
if(fabs(x)<eps)return 0;
if(x<0)return -1;
return 1;
}
int cmp(double x,double y){
if(fabs(x-y)<eps)return 0;
if(x<y)return -1;
return 1;
}
-
向量
-
向量的加减和数乘。 -
内积(点积)
A
?
B
=
∣
A
∣
∣
B
∣
c
o
s
(
C
)
A \cdot B=|A||B|cos(C)
A?B=∣A∣∣B∣cos(C) 几何意思:向量A在向量B上的投影乘向量B的长度。 double dot(Point a,Point b){
return a.x*b.x+a.y*b.y;
}
-
外积(叉积)
A
×
B
=
∣
A
∣
∣
B
∣
s
i
n
(
C
)
A \times B = |A||B|sin(C)
A×B=∣A∣∣B∣sin(C) (行列式推的) 几何意义:向量A和B张成的平行四边形的面积(有向面积)的一半。方向遵循定则。 double cross(Point a,Point b){
return a.x*b.y-a.y*b.x
}
-
由点积和叉积延伸出来的常用函数。
-
求向量的长度。 double get_length(Point a){
return sqrt(dot(a,a));
}
-
计算向量的夹角 double get_angle(Point a,Point b){
return acos(dot(a,b)/get_length(a)/get_length(b));
}
-
计算平行四边形面积 double get_area(Point a,Point b,Point c){
return cross(a-b,c-b);
}
-
将一个向量旋转一个角度。 将
(
x
,
y
)
(x,y)
(x,y) 顺时针旋转一个
θ
\theta
θ 角。
[
x
,
y
]
[
c
o
s
(
θ
)
?
s
i
n
(
θ
)
s
i
n
(
θ
)
c
o
s
(
θ
)
]
=
[
x
c
o
s
(
θ
)
+
y
s
i
n
(
θ
)
,
?
x
s
i
n
(
θ
)
+
y
c
o
s
(
θ
)
]
\begin{bmatrix} x , y \end{bmatrix} \begin{bmatrix} cos(\theta) & -sin(\theta)\\ sin(\theta) &cos(\theta) \end{bmatrix}=[{xcos(\theta)+ysin(\theta)},{-xsin(\theta)+ycos(\theta)}]
[x,y?][cos(θ)sin(θ)??sin(θ)cos(θ)?]=[xcos(θ)+ysin(θ),?xsin(θ)+ycos(θ)] -
点与线
-
直线定理。
- 一般式
a
x
+
b
y
+
c
=
0
ax+by+c=0
ax+by+c=0
- 点向式(用的最多)
p
0
(
任
意
一
个
点
)
+
v
 ̄
(
过
p
0
的
非
0
向
量
)
?
t
p_0(任意一个点)+\overline v(过p_0的非0向量) *t
p0?(任意一个点)+v(过p0?的非0向量)?t
- 斜截式 $y = kx+b
-
判断点在不在直线上。
A
×
B
=
0
A \times B = 0
A×B=0 表示
a
点
和
向
量
B
上
的
某
个
点
组
成
的
向
量
A
和
B
所
围
成
的
三
角
形
的
面
积
是
0
a点和向量B上的某个点组成的向量A和B所围成的三角形的面积是0
a点和向量B上的某个点组成的向量A和B所围成的三角形的面积是0 ,表示点在直线上。 -
两直线相交,求交点。
c
r
o
s
s
(
v
,
w
)
=
=
0
cross(v,w)==0
cross(v,w)==0 特判两直线平行或者重合的情况。(用了相似来证明) Point get_intersection(Point p,Vector v,Point q,Vector w){
Vector u = p-q;
double t = cross(w,u)/cross(v,w);
return p+v*t;
}
-
点到直线的距离。 double distance_to_line(Point a,Point b,Point c){
Vector v1 = b-a;
Vector v2 = c-a;
return fabs(cross(v1,v2))/getlength(v1);
}
-
点到线段的距离。特判两种特殊情况。 double distance_to_segment(Point p,Point a,Point b){
if(a==b)return get_length(p-a);
Vector v1 = b-a,v2=p-a,v3=p-b;
if(sign(dot(v1,v2))<0)return get_length(v2);
if(sign(dot(v1,v3))>0)return get_length(v3);
return distance_to_line(p,a,b);
}
-
点到直线的投影。 Point get_line_projection(Point P,Point a,Point b){
Vector v = b-a;
return a+v*(dot(v,p-a)/dot(v,v));
}
-
点是否在线段上。 bool on_segment(Point p,Point a,Point b){
return sign(cross(p-a),cross(p-b)) == 0 && sign(dot(p-a,p-b))<=0;
}
-
判断两线段是否相交 (跨立实验) bool segment_intersection(Point a1,Point a2,Point b1,Point b2){
double c1 = cross(a2-a1,b1-a1);
double c2 = cross(a2-a1,b2-a1);
double c3 = cross(b2-b1,a2-b1);
double c4 = cross(b2-b1,a1-b1);
return sign(c1)*sign(c2)<=0 && sign(c3)*sign(c4)<=0;
}
-
多边形。
-
三角形的四心。
- 外心:三角形外接圆的圆心,三边的中垂线的交点,到三角形的三个顶点的距离相等。
- 内心:内切圆的圆心,角平分线的交点,到三边的距离相等。
- 垂心:三个垂足的交点。
- 重心:三条中线的交点。(到三角形三顶点距离的平方和最小的点,三角形内到三边距离的乘积最大的点)。
-
定义:在同一平面,不在同一直线上,多条线段首尾顺次连接且不相交的图形。 -
简单多边形:除相邻边外,其他边不相交。 -
凸多边形: 过多边形的任意一条边做一条直线,如果其他各个顶点都在这条边的一侧,就是凸多边形。
- 任意凸多边形的外角和都是360度。
- 任意凸多边形的内角和都是
(
n
?
2
)
?
180
(n-2)*180
(n?2)?180度。
-
常用函数:
-
求任意多边形的面积。 可以将多边形进行三角剖分,分成
n
?
2
n-2
n?2 个三角形,将所有的边按照逆序,或者顺序进行排序。 -
可以在平面上任意选一点,按照边的顺序,遍历每一条边,通过求两个向量的叉积的方法,得到多边形的面积和。(利用了叉积面积有正负的性质,非常的巧妙) double polygon_area(Point p[],int n){
double s=0;
for(int i=1;i<n-1;i++){
s += cross(p[i]-p[0],p[i+1]-p[i]);
}
return s/2;
}
-
判断一个点是否在多边形内(可以是任意多边形) 射线法 or 转角法 射线法:从该点任意做一条和所有边都不平行的射线,交点个数为偶数,该点在多边形外,否则在多边形内。 -
判断一个点是否在凸多边形内(凸多边形按照逆时针存储) 判断点是否在凸多边形的左侧。(叉积) -
皮克定理 ? 要求:多边形的所有点必须在格点上。 ?
s
=
a
+
b
2
?
1
s = a + {b\over 2}-1
s=a+2b??1 。 ?
a
:
a:
a:多边形内部的整点个数。 ?
b
:
b:
b: 多边形边上的整点个数。
|