计算几何模板
基础模板:
1 const double eps = 1e-10; 2 const double pi = 3.1415926535897 ; 3 struct Point 4 { 5 double x, y; 6 Point(double x = 0, double y = 0):x(x), y(y){} 7 }; 8 typedef Point Vector; 9 10 struct Line//有向直线 11 { 12 Point P;//直线上任意一点 13 Vector v;//方向向量(左边就是对应的半平面) 14 double ang;//极角,即从x正半轴旋转到向量v所需要的角(弧度) 15 Line(Point P, Vector v):P(P), v(v){ang = Angle(v);} 16 bool operator < (const Line& L)const 17 { 18 return ang < L.ang; 19 } 20 }; 21 Vector operator + (Vector A, Vector B){return Vector(A.x+B.x, A.y+B.y);}//向量+向量=向量;点+向量=向量 22 Vector operator - (Vector A, Vector B){return Vector(A.x-B.x, A.y-B.y);}//点-点=向量 23 Vector operator * (Vector A, double p){return Vector(A.x*p, A.y*p);}//向量*数=向量 24 Vector operator / (Vector A, double p){return Vector(A.x/p, A.y/p);}//向量/数=向量 25 bool operator < (const Point& a, const Point& b) 26 { 27 return a.x < b.x || (a.x == b.x && a.y < b.y); 28 } 29 int dcmp(double x)//三态函数,高精度判断 30 { 31 if(fabs(x) < eps)return 0; else return x < 0 ? -1 : 1; 32 } 33 bool operator == (const Point& a, const Point& b) 34 { 35 return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0; 36 } 37 double Dot(Vector A, Vector B){return A.x*B.x + A.y*B.y;}//点积 38 double Length(Vector A){return sqrt(Dot(A, A));}//长度 39 double Angle(Vector A){return atan2(A.y, A.x);}//向量A的极角(弧度) 40 double Angle(Vector A, Vector B){return acos(Dot(A, B) / Length(A) / Length(B));}//向量A,B夹角 41 double Cross(Vector A, Vector B){return A.x*B.y - A.y*B.x;}//叉积 42 double Area2(Point A, Point B, Point C){return Cross(B-A, C-A);}//三角形有向面积的两倍 43 Vector Rotate(Vector A, double rad) 44 //向量A逆时针旋转rad(弧度) 45 { 46 return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad)); 47 } 48 Vector Normal(Vector A) 49 //返回A的单位法线,调用前保证A非零 50 { 51 double L = Length(A); 52 return Vector(-A.y/L, A.x/L); 53 } 54 55 Point GetlineIntersection(Point P, Vector v, Point Q, Vector w)//(参数式) 56 //求直线P+tv和Q+tw交点(t为参数)。调用前确保有交点,无交点当且仅当Cross(v, w) = 0; 57 { 58 Vector u = P - Q; 59 double t = Cross(w, u) / Cross(v, w); 60 return P + v*t; 61 } 62 Point GetlineIntersectionB(Point P, Point X, Point Q, Point Y)//(两点式) 63 //求直线PX和QY交点(t为参数)。调用前确保有交点,无交点当且仅当Cross(v, w) = 0; 64 { 65 Vector v = X - P, w = Y - Q; 66 return GetlineIntersection(P, v, Q, w); 67 } 68 double DistanceToLine(Point P, Point A, Point B) 69 //点P到直线AB的距离 70 { 71 Vector v1 = B - A, v2 = P - A; 72 return fabs(Cross(v1, v2) / Length(v1)); 73 } 74 double DistanceToSegment(Point P, Point A, Point B) 75 //点P到线段AB的距离 76 { 77 if(A == B)return Length(P-A); 78 Vector v1 = B - A, v2 = P - A, v3 = P - B; 79 if(dcmp(Dot(v1, v2)) < 0)return Length(v2); 80 else if(dcmp(Dot(v1, v3)) > 0)return Length(v3); 81 else return fabs(Cross(v1, v2)) / Length(v1); 82 } 83 Point GetlineProjection(Point P, Point A, Point B) 84 //点P在直线AB上的投影 85 { 86 Vector v = B - A; 87 return A + v *(Dot(v, P-A) / Dot(v,v)); 88 } 89 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2) 90 //判断线段a1a2和b1b2是否规范相交(在端点处相交得用下一个函数特殊判断) 91 { 92 double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1), 93 c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1); 94 return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0; 95 } 96 bool OnSegment(Point p, Point a1, Point a2)//在线段上返回1,不在返回0 97 //判断点P是否在线段a1a2上(不包括端点) 98 { 99 return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0; 100 } 101 bool OnSegment2(Point p, Point a1, Point a2)//在线段上返回1,不在返回0 102 //判断点P是否在线段a1a2上(包括端点) 103 { 104 return OnSegment(p, a1, a2) || p == a1 || p == a2; 105 }
多边形:
1 //多边形面积 2 double PolygonArea(Point* p, int n) 3 { 4 double area = 0; 5 for(int i = 1; i < n - 1; i++) 6 area += Cross(p[i] - p[0], p[i + 1] - p[0]); 7 return area / 2; 8 } 9 10 //点在多边形内判定 11 int isPointInPolygon(Point p, Point * poly, int n) 12 { 13 int wn = 0; 14 for(int i = 0; i < n; i++) 15 { 16 if(OnSegment2(p, poly[i], poly[(i + 1) % n]))return -1;//点在多边形边界上 17 int k = dcmp(Cross(poly[(i + 1) % n] - poly[i], p - poly[i])); 18 int d1 = dcmp(poly[i].y - p.y); 19 int d2 = dcmp(poly[(i + 1) % n].y - p.y); 20 if(k > 0 && d1 <= 0 && d2 > 0)wn++; 21 if(k < 0 && d2 <= 0 && d1 > 0)wn--; 22 } 23 if(wn != 0)return 1;//内部 24 return 0;//外部 25 } 26 27 //凸包:输入点数组p,个数为n,输出点数组为ch,返回输出点个数 28 //输入不能有重复点,函数执行完输入点顺序被破坏 29 //如果不希望凸包的边上存在输入点,把两个<=改成< 30 int ConvexHull(Point* p, int n, Point * ch) 31 { 32 sort(p, p + n); 33 int m = 0; 34 for(int i = 0; i < n; i++) 35 { 36 while(m > 1 && dcmp(Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2])) <= 0)m--;//可将此处的<=改成<,保证凸包的边上没有点 37 ch[m++] = p[i]; 38 } 39 int k = m; 40 for(int i = n - 2; i >= 0; i--) 41 { 42 while(m > k && dcmp(Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2])) <= 0)m--; 43 ch[m++] = p[i]; 44 } 45 if(n > 1)m--; 46 return m; 47 }
圆
1 struct Circle 2 { 3 Point c;//圆心 4 double r;//半径 5 Circle(){} 6 Circle(Point c, double r):c(c), r(r){} 7 Point point(double a)//在圆上圆心角为a的点 8 { 9 return Point(c.x + cos(a) * r, c.y + sin(a) * r); 10 } 11 };
越努力,越幸运