计算几何全家桶(基础)
计算几何全家桶(基础)
其实只是记录一些可能会用到的非常基础的东西(懒得多次反复写了)。
一:【准备工作】
#include <bits/stdc++.h>
#define dd double
using namespace std;
const int N=1e5;const dd eps=1e-8,PI=acos(-1.0);
int jd(dd x){return a<-eps?-1:(a>eps?1:0);}//精度控制
dd ABS(dd x){return x*jd(x);}//求绝对值
struct d{
dd x,y;d(X=0,Y=0){x=X;y=Y;}
void in(){scanf("%lf%lf",&x,&y);}
void out(){printf("%.5lf %.5lf\n",x,y);}
};//结构体存点或向量 以及输入输出
没啥好说的,就是一些初始化。
二:【向量】
1.【模】
对于 \(\vec{a}=(x,y)\),\(\left| \vec{a} \right| = \sqrt{x^2+y^2}=\sqrt{\left| \vec{a} \right|^2}=\sqrt{\vec{a} \vec{a}}\),所以可以用下面的 点积 解决。
dd len(d a){return sqrt(dj(a,a);}//模
2.【向量加减】
对于 \(\vec{a}=(x_1,y_1),\vec{b}=(x_2,y_2)\),\(\vec{a}+\vec{b}=(x_1+x_2,y_1+y_2)\)
对于 \(\vec{a}=(x_1,y_1),\vec{b}=(x_2,y_2)\),\(\vec{a}-\vec{b}=(x_1-x_2,y_1-y_2)\)
d operator+(d a,d b){return d(a.x+b.x,a.y+b.y);}
d operator-(d a,d b){return d(a.x-b.x,a.y-b.y);}
3.【向量数乘】
对于 \(\vec{a}=(x,y)\), \(\lambda \vec{a}=(\lambda x,\lambda y)\)
对于 \(\vec{a}=(x,y)\), \(\dfrac{\vec{a}}{\lambda} = \left( \dfrac{x}{\lambda} , \dfrac{y}{\lambda} \right)\)(其实向量除就是向量乘的逆运算)
d operator*(d a,dd b){return d(a.x*b,a.y*b);}
d operator/(d a,dd b){return d(a.x/b.a.y/b);}
4.【向量点积(数量积)(内积)】
定义:\(\vec{a} \cdot \vec{b} = \left| \vec{a} \right| \left| \vec{b} \right| \cos \theta \left(\theta = \left<\vec{a},\vec{b}\right> \right)\)
对于 \(\vec{a}=(x_1,y_1),\vec{b}=(x_2,y_2)\),\(\vec{a} \cdot \vec{b}=x_1x_2+y_1y_2\)
夹角 \(\theta\) 与点积的关系:
- \(\theta = 0^\circ\),\(\vec{a} \cdot \vec{b} = \left| \vec{a} \right| \left| \vec{b} \right|\)
- \(\theta = 180^\circ\),\(\vec{a} \cdot \vec{b} = - \left| \vec{a} \right| \left| \vec{b} \right|\)
- \(\theta < 90^\circ\),\(\vec{a} \cdot \vec{b} >0\)
- \(\theta = 90^\circ\),\(\vec{a} \cdot \vec{b} =0\)
- \(\theta > 90^\circ\),\(\vec{a} \cdot \vec{b} <0\)
dd dj(d a,d b){return a.x*b.x+a.y*b.y;}//点积
5.【向量叉积(向量积)(外积)】
定义:\(\vec{a} \times \vec{b} = \left| \vec{a} \right| \left| \vec{b} \right| \sin \theta \left(\theta = \left<\vec{a},\vec{b}\right> \right)\)
对于 \(\vec{a}=(x_1,y_1),\vec{b}=(x_2,y_2),\vec{a} \times \vec{b} = x_1y_2+x_2y_1\)
向量 \(\vec{a},\vec{b}\) 的位置与叉积的关系:
- \(\vec{a} // \vec{b},\vec{a} \times \vec{b} =0\)
- \(\vec{a}\) 在 \(\vec{b}\) 左侧,\(\vec{a} \times \vec{b} < 0\)
- \(\vec{a}\) 在 \(\vec{b}\) 右侧,\(\vec{a} \times \vec{b} > 0\)
dd cj(d a,d b){return a.x*b.y-a.y*b.x;}//叉积
6.【向量夹角】
因为 \(\vec{a} \cdot \vec{b} = \left| \vec{a} \right| \left| \vec{b} \right| \cos \theta \left(\theta = \left<\vec{a},\vec{b}\right> \right)\),所以 \(\cos \theta =\dfrac{ \vec{a} \cdot \vec{b} } {\left| \vec{a} \right| \left| \vec{b} \right| } \left(\theta = \left<\vec{a},\vec{b}\right> \right)\)
dd angle(d a,d b){return acos(dj(a,b)/len(a)/len(b));}//两向量夹角
三:【点、向量的位置变换】
1.【点、向量绕原点的旋转】
对于点或向量 \((x,y)\),将其顺时针旋转 \(\theta\) 度: \(\begin{vmatrix} x&y \end{vmatrix} \times \begin{vmatrix} \cos \theta & - \sin \theta \\ \sin \theta & \cos \theta \end{vmatrix} = \begin{vmatrix} x \cos \theta + y \sin \theta & -x \sin \theta + y \cos \theta \end{vmatrix}\)
d turn(d a,dd theta){
dd x=a.x*cos(theta)+a.y*sin(theta);
dd y=-a.x*sin(theta)+a.y*cos(theta);
return d(x,y);
}//点或向量 A 绕原点顺时针旋转 theta 度
2.【点绕点的旋转】
对于点 \(A(x_1,y_1)\) 绕点 \(B(x_2,y_2)\) 顺时针旋转 \(\theta\) 度: \(\begin{vmatrix} (x_1-x_2) \cos \theta + (y_1-y_2) \sin \theta + x_2 & -(x_1-x_2) \sin \theta + (y_1-y_2) \cos \theta +y_2 \end{vmatrix}\)
d turn_(d a,d b,dd theta){
dd x=(a.x-b.x)*cos(theta)+(a.y-b.y)*sin(theta)+b.x;
dd y=-(a.x-b.x)*sin(theta)+(a.y-b.y)*cos(theta)+b.y;
return d(x,y);
}//点 A 绕点 B 顺时针旋转 theta 度
3.【法向量】
对于向量 \(\vec{a}=(x,y)\),法向量就是垂直于向量 \(\vec{a}\) 的向量。
联系上面的向量绕原点旋转可知,求一个向量的法向量就是将这个向量顺时针旋转 \(90^\circ\)。
d Normal(d a){return d(-a.y,a.x);}//求法向量
计算几何全家桶(基础)综合代码
#include <bits/stdc++.h>
#define dd double
using namespace std;
/*--------------------------------------------*/
const int N=1e5;const dd eps=1e-8,PI=acos(-1.0);
int jd(dd x){return x<-eps?-1:(x>eps?1:0);}//精度控制
dd ABS(dd x){return x*jd(x);}//求绝对值
struct d{
dd x,y;d(dd X=0,dd Y=0){x=X;y=Y;}
void in(){scanf("%lf%lf",&x,&y);}
void out(){printf("%.5lf %.5lf\n",x,y);}
};//结构体存点或向量 以及输入输出
/*--------------------------------------------*/
dd dj(d a,d b){return a.x*b.x+a.y*b.y;}//点积
dd cj(d a,d b){return a.x*b.y-a.y*b.x;}//叉积
dd len(d a){return sqrt(dj(a,a));}//模
dd angle(d a,d b){return acos(dj(a,b)/len(a)/len(b));}//两向量夹角
/*向量四则运算*/
d operator+(d a,d b){return d(a.x+b.x,a.y+b.y);}
d operator-(d a,d b){return d(a.x-b.x,a.y-b.y);}
d operator*(d a,dd b){return d(a.x*b,a.y*b);}
d operator/(d a,dd b){return d(a.x/b,a.y/b);}
d Normal(d a){return d(-a.y,a.x);}//求法向量
bool operator==(d a,d b){return !jd(a.x-b.x)&&!jd(a.y-b.y);}//判相等
/*-------------------------------------------*/
d turn(d a,dd theta){
dd x=a.x*cos(theta)+a.y*sin(theta);
dd y=-a.x*sin(theta)+a.y*cos(theta);
return d(x,y);
}//点或向量 A 绕原点顺时针旋转 theta 度
d turn_(d a,d b,dd theta){
dd x=(a.x-b.x)*cos(theta)+(a.y-b.y)*sin(theta)+b.x;
dd y=-(a.x-b.x)*sin(theta)+(a.y-b.y)*cos(theta)+b.y;
return d(x,y);
}//点 A 绕点 B 顺时针旋转 theta 度
/*-------------------------------------------*/
int main(){}