[模板仓库] 计算几何
未完待续
点:
1 struct point{ 2 double x,y; 3 point operator + (point b){return (point){x+b.x,y+b.y};}; 4 point operator - (point b){return (point){x-b.x,y-b.y};}; 5 point operator * (double v){return (point){x*v,y*v};} 6 point operator / (double v){return (point){x/v,y/v};} 7 }p[mxn];
结构体大法好
线:
线段的话,开个结构体存两个端点
直线的话:
1 typedef point Vector; 2 struct Line{ 3 point x; 4 Vector v; 5 double alpha; 6 int id; 7 void getang(){ 8 alpha=atan2(v.y,v.x); 9 if(alpha<0)alpha+=pi*2; 10 } 11 bool operator < (Line b)const{return alpha<b.alpha;} 12 }a[mxn];
存一个点+一个方向向量,alpha存相对于水平位置的角度。
atan2()返回角度范围是-pi ~ +pi
向量运算:
点距离:
1 double dist(point a,point b){ 2 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 3 }
长度:
1 double Len(Vector a){ 2 return sqrt((a.x*a.x)+(a.y*a.y)); 3 }
点积:
1 double dot (point a,point b){return a.x*b.x+a.y*b.y;}
叉积:
向量a x 向量b ,若b在a的逆时针方向,返回结果为正;若b在a的顺时针方向,返回结果为负;同向或反向时结果为0
1 inline double Cross(Point a,Point b){return a.x*b.y-a.y*b.x;}
向量逆时针旋转(弧度制):
1 point spin(point a,double ang){ 2 return point(a.x*cos(ang)-a.y*sin(ang),a.x*sin(ang)+a.y*cos(ang)); 3 }
直线交点:
利用三角形面积列出两个式子,消一下即可。
↑右边灰色部分应该是$ (k2-1)v2 $
1 Point intersec(Point a,Point v,Point b,Point w){ 2 Point v1=a-b; 3 double t=Cross(w,v1)/Cross(v,w); 4 return a+v*t; 5 }
判断两直线的位置关系:POJ1269 Intersecting Lines
半平面:
用射线表示界线,射线的“左边”是半平面
圆:
1 struct cir{ 2 double x,y; 3 double r; 4 point operator + (cir b){return (point){x+b.x,y+b.y};} 5 point operator - (cir b){return (point){x-b.x,y-b.y};} 6 }c[mxn]; 7 inline bool cover(cir a,cir b){ 8 return (a.r>=b.r+Len(a-b)); 9 }
圆心角计算:Bzoj1313 [HAOI2008]下落的圆盘
最小圆覆盖:ZOJ1450 Minimal Circle
凸包:
Graham算法:选定最靠边的一个点,将其他的所有点按向量极角排序,用单调栈维护。
Andrew算法:按横坐标排序,先从左往右扫一遍搞出一个下凸壳,再从右往左扫一遍搞出一个上凸壳,用单调栈维护。
半平面交
将直线按极角排序,记录两两之间的交点。单调栈维护直线,若新加入的直线会覆盖旧直线,就把旧直线退栈
旋转卡壳
有二十四种读音的神奇算法。
扫描线:
各种定理:
picks定理:设平面直角坐标系中,一个三角形内部有a个整坐标点,它的三条边共经过了b个整坐标点,那么三角形面积$ S=a + b/2 -1 $
本文为博主原创文章,转载请注明出处。