计算几何全家桶(基础)

计算几何全家桶(基础)

其实只是记录一些可能会用到的非常基础的东西(懒得多次反复写了)。

一:【准备工作】

#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(){}
posted @ 2022-03-14 22:42  AIskeleton  阅读(57)  评论(0编辑  收藏  举报