计算几何模板

基础模板

 

  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 };

 

posted @ 2018-07-19 23:02  _努力努力再努力x  阅读(182)  评论(0编辑  收藏  举报