计算几何模板(自己打的参与修正)(刘汝佳)

//
//  main.cpp
//  demo
//
//  Created by Yanbin GONG on 14/4/2018.
//  Copyright © 2018 Yanbin GONG. All rights reserved.
//

//向量的基本运算

#include <cmath>
#include <vector>

using namespace std;


//基本定义
struct Point{
    double x,y;
    Point(double x=0, double y=0):x(x),y(y){}//构造函数方便代码编写
};
typedef Point Vector; //程序实现上, Vector只是Point的别名(因为起点挪到了原点)

Vector operator + (Vector A, Vector B) {return Vector(A.x+B.x,A.y+B.y);}
Vector operator - (Vector A, Vector B) {return Vector(A.x-B.x,A.y-B.y);}
Vector operator * (Vector A, double p) {return Vector(A.x*p,A.y*p);}
Vector operator / (Vector A, double p) {return Vector(A.x/p,A.y/p);}

// const &的作用是直接引用但是不改变,会节约内存
bool operator < (const Point& a, const Point& b){
    return a.x<b.x || (a.x==b.x&&a.y<b.y);
}

const double eps = 1e-10; //设置精度在小数点后十位
//如果两个数的差距小于这个数字就当做他们相等

//判断这个数是为0,还是小于0,还是大于0
int dcmp(double x){
    //fabs为绝对值函数
    if(fabs(x)<eps)return 0; //fabs在cmath里
    else return x<0? -1:1;
}

bool operator == (const Point& a, const Point& b){
    return (dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0);
}

//向量基本运算
double Dot(Vector A, Vector B) {return A.x*B.x + A.y*B.y;}//点积
double Length(Vector A) {return sqrt(Dot(A,A));}//自身乘积再开根号保证绝对值稳定性
double Angle(Vector A, Vector B) {return acos(Dot(A,B)/Length(A)/Length(B));}

//叉乘
double Cross(Vector A, Vector B) {return A.x*B.y-A.y*B.x;}
double Area2(Point A, Point B, Point C) {return Cross(B-A, C-A);}//相当于上面的为原点,为面积的两倍

//角度转弧度
double torad(double deg)
{
    return deg/180*acos(-1);
}
//旋转
Vector Rotate(Vector A, double rad) {
    return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}

//单位法线
Vector Normal(Vector A){
    double L = Length(A);
    return Vector(-A.y/L,A.x/L);
}

//点和直线

//两条直线的交点
//一条直线可以写成一个点和一个向量(方向)
//
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){
    Vector u = P-Q;
    double t = Cross(w,u)/Cross(v,w);
    return P+v*t;
}

//点到直线的距离
double DistanceToLine(Point P, Point A, Point B){
    Vector v1=B-A, v2=P-A;
    return fabs(Cross(v1,v2))/Length(v1); //如果不取绝对值,得到的是有向距离
}

//点到线段的距离
double DistanceToSegment(Point P, Point A, Point B){
    if(A==B) return Length(P-A);
    Vector v1=B-A, v2=P-A, v3=P-B;
    //投影不在线段上的情况
    if(dcmp(Dot(v1,v2))<0) return Length(v2); //P在靠A侧
    else if(dcmp(Dot(v1,v3))>0) return Length(v3); //在靠近B的一侧
    else return fabs(Cross(v1,v2))/Length(v1);
}

//点在直线上的投影
Point GetLineProjection(Point P, Point A, Point B){
    Vector v=B-A;
    return A+v*(Dot(v,P-A)/Dot(v,v)); //从A移动到投影
}

//线段相交判定 相交为1 (交点不为任何一线段的端点)
bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2){
    double c1 = Cross(a2-a1,b1-a1);
    double c2 = Cross(a2-a1,b2-a1);
    double c3 = Cross(b2-b1,a1-b1);
    double c4 = Cross(b2-b1,a2-b1);
    return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}
//判断一个点是否在一条线段上(用于判断一个端点是否在另一个线段上)
//如果c1 c2窦唯0,则线段共线
bool OnSegment(Point p, Point a1, Point a2){
    return dcmp(Cross(a1-p, a2-p))==0 && dcmp(Dot(a1-p, a2-p))<0;
}

//与圆和球有关的计算问题

struct Line{
    Point p;//线上一点
    Vector v;//方向向量
    double ang; //极角,从x正半轴旋转到v所需要的角(弧度)
    Line(Point p, Vector v):p(p),v(v){ang = atan2(v.y,v.x);}
    Point point(double t){return p+v*t;};
    bool operator < (const Line& L) const{ //排序用的比较运算符
        return ang < L.ang;
    }
};

struct Circle{
    Point c;
    double r;
    Circle(Point c, double r):c(c),r(r){}
    Point point(double a){ //通过圆心角求坐标的函数
        return Point(c.x+cos(a)*r,c.y+sin(a)*r);
    }
};

//直线与圆的交点
//sol存放的是交点本身,代码没有清空sol,就很方便:可以反复调用把所有交点放在一个sol里
int getLineCircleIntersection(Line L, Circle C, double& t1, double& t2, vector<Point>& sol){
    double a=L.v.x, b=L.p.x-C.c.x, c=L.v.y, d=L.p.y-C.c.y;
    double e=a*a+c*c, f=2*(a*b+c*d), g=b*b+d*d-C.r*C.r;
    double delta = f*f - 4*e*g;//判别式
    if(dcmp(delta)<0) return 0; //相离
    if(dcmp(delta)==0){
        t1=t2=-f/(2*e);
        sol.push_back(L.point(t1));
        return 1;
    }
    //相交
    t1 = (-f-sqrt(delta))/(2*e);
    sol.push_back(L.point(t1));
    t2 = (-f+sqrt(delta))/(2*e);
    sol.push_back(L.point(t2));
    return 2;
}

//计算向量极角
double angle(Vector v){return atan2(v.y,v.x);}

//两圆相交
int getCircleCircleIntersection(Circle C1, Circle C2, vector<Point>& sol){
    double d=Length(C1.c-C2.c);
    if(dcmp(d)==0){
        if(dcmp(C1.r-C2.r)==0) return -1; //两圆重合
        return 0;
    }
    if(dcmp(C1.r+C2.r-d)<0) return 0; //内含
    if(dcmp(fabs(C1.r-C2.r)-d)>0) return 0; //外离
    
    double a = angle(C2.c-C1.c); //向量C1C2的极角
    double da = acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));
    //C1C2到C1P1的角
    Point p1 = C1.point(a-da), p2 = C1.point(a+da);
    
    sol.push_back(p1);
    if(p1==p2)return 1;
    sol.push_back(p2);
    return 2;
}

//过定点作圆切线,v[i]是第i条切线,返回切线条数
int getTangents(Point p, Circle C, Vector* v){
    Vector u = C.c-p;
    double dist = Length(u);
    if(dist<C.r) return 0;
    else if(dcmp(dist-C.r)==0){ //p在圆上,只有一条切线
        v[0]=Rotate(u,M_PI/2);
        return 1;
    }
    else{
        double ang = asin(C.r/dist);
        v[0] = Rotate(u, -ang);
        v[1] = Rotate(u, +ang);
        return 2;
    }
}

//两圆的公切线
int getTangents(Circle A, Circle B, Point* a, Point* b){
    int cnt=0;
    if(A.r<B.r){
        swap(A,B);
        swap(a,b);
    }
    int d2=(A.c.x-B.c.x)*(A.c.x-B.c.x)+(A.c.y-B.c.y)*(A.c.y-B.c.y);
    int rdiff=A.r-B.r;
    int rsum=A.r+B.r;
    if(d2<rdiff*rdiff) return 0; //内含
    double base = atan2(B.c.y-A.c.y,B.c.x-A.c.x);
    if(d2==0&&A.r==B.r) return -1; //无限多条切线
    if(d2==rdiff*rdiff){//内切,一条切线
        a[cnt]=A.point(base);
        b[cnt]=B.point(base);
        cnt++;
        return 1;
    }
    //有外共切线
    double ang = acos(A.r-B.r)/sqrt(d2);
    a[cnt] = A.point(base+ang);
    b[cnt] = B.point(base+ang);
    cnt++;
    a[cnt] = A.point(base+ang);
    b[cnt] = B.point(base-ang);
    cnt++;
    if(d2==rsum*rsum){
        a[cnt]=A.point(base);
        b[cnt]=B.point(M_PI+base);
        cnt++;
    }
    else if(d2>rsum*rsum){
        double ang=acos((A.r+B.r)/sqrt(d2));
        a[cnt]=A.point(base+ang);
        b[cnt]=B.point(M_PI+base+ang);
        cnt++;
        a[cnt]=A.point(base-ang);
        b[cnt]=B.point(M_PI+base-ang);
        cnt++;
    }
    return cnt;
}

//三角形外接圆(三点保证不共线)
Circle CircumscribedCircle(Point p1, Point p2, Point p3){
    double Bx = p2.x-p1.x, By = p2.y-p1.y;
    double Cx = p3.x-p1.x, Cy = p3.y-p1.y;
    double D = 2*(Bx*Cy-By*Cx);
    double cx = (Cy*(Bx*Bx+By*By)-By*(Cx*Cx+Cy*Cy))/D+p1.x;
    double cy = (Bx*(Cx*Cx+Cy*Cy)-Cx*(Bx*Bx+By*By))/D+p1.y;
    Point p = Point(cx,cy);
    return Circle(p,Length(p1-p));
}
//三角形内切圆
Circle InscribedCircle(Point p1, Point p2, Point p3){
    double a = Length(p2-p3);
    double b = Length(p3-p1);
    double c = Length(p1-p2);
    Point p = (p1*a+p2*b+p3*c)/(a+b+c);
    return Circle(p, DistanceToLine(p, p1, p2));
}


//二维几何常用算法
typedef vector<Point> Polygon;
//多边形的有向面积
double PolygonArea(Polygon po) {
    int n = po.size();
    double area = 0.0;
    for(int i = 1; i < n-1; i++) {
        area += Cross(po[i]-po[0], po[i+1]-po[0]);
    }
    return area * 0.5;
}

//点在多边形内判定
int isPointInPolygon(Point p, Polygon poly){
    int wn = 0; //绕数
    int n = poly.size();
    for(int i=0;i<n;i++){
        if(OnSegment(p,poly[i],poly[(i+1)%n])) return -1;//边界上
        int k = dcmp(Cross(poly[(i+1)%n]-poly[i], p-poly[i]));
        int d1 = dcmp(poly[i].y-p.y);
        int d2 = dcmp(poly[(i+1)%n].y-p.y);
        if(k>0&&d1<=0&&d2>0) wn++;
        if(k<0&&d2<=0&&d1>0) wn--;
    }
    if(wn!=0) return 1;//内部
    return 0;//外部
}

//凸包
//Andrew算法
bool myCmp(Point A, Point B)
{
    if(A.x != B.x)    return A.x < B.x;
    else return A.y < B.y;
}

int ConvexHall (Point* p, int n, Point* ch){
    sort(p,p+n,myCmp); //先比较x坐标,再比较y坐标
    int m = 0;
    for(int i=0;i<n;i++){
        while(m>1&&Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])<=0) m--;
        ch[m++] = p[i];
    }
    if(n>1)m--;
    return m;
}
//凸包(Andrew算法)  
//如果不希望在凸包的边上有输入点,把两个 <= 改成 <  
//如果不介意点集被修改,可以改成传递引用  
Polygon ConvexHull(vector<Point> p) {  
    //预处理,删除重复点  
    sort(p.begin(), p.end());  
    p.erase(unique(p.begin(), p.end()), p.end());  
    int n = p.size(), m = 0;  
    Polygon res(n+1);  
    for(int i = 0; i < n; i++) {  
        while(m > 1 && Cross(res[m-1]-res[m-2], p[i]-res[m-2]) <= 0) m--;  
        res[m++] = p[i];  
    }  
    int k = m;  
    for(int i = n-2; i >= 0; i--) {  
        while(m > k && Cross(res[m-1]-res[m-2], p[i]-res[m-2]) <= 0) m--;  
        res[m++] = p[i];  
    }  
    m -= n > 1;  
    res.resize(m);  
    return res;  
}  
 

 

  1 //
  2 //  main.cpp
  3 //  demo
  4 //
  5 //  Created by Yanbin GONG on 14/4/2018.
  6 //  Copyright © 2018 Yanbin GONG. All rights reserved.
  7 //
  8 
  9 //向量的基本运算
 10 
 11 #include <cmath>
 12 #include <vector>
 13 
 14 using namespace std;
 15 
 16 
 17 //基本定义
 18 struct Point{
 19     double x,y;
 20     Point(double x=0, double y=0):x(x),y(y){}//构造函数方便代码编写
 21 };
 22 typedef Point Vector; //程序实现上, Vector只是Point的别名(因为起点挪到了原点)
 23 
 24 Vector operator + (Vector A, Vector B) {return Vector(A.x+B.x,A.y+B.y);}
 25 Vector operator - (Vector A, Vector B) {return Vector(A.x-B.x,A.y-B.y);}
 26 Vector operator * (Vector A, double p) {return Vector(A.x*p,A.y*p);}
 27 Vector operator / (Vector A, double p) {return Vector(A.x/p,A.y/p);}
 28 
 29 // const &的作用是直接引用但是不改变,会节约内存
 30 bool operator < (const Point& a, const Point& b){
 31     return a.x<b.x || (a.x==b.x&&a.y<b.y);
 32 }
 33 
 34 const double eps = 1e-10; //设置精度在小数点后十位
 35 //如果两个数的差距小于这个数字就当做他们相等
 36 
 37 //判断这个数是为0,还是小于0,还是大于0
 38 int dcmp(double x){
 39     //fabs为绝对值函数
 40     if(fabs(x)<eps)return 0; //fabs在cmath里
 41     else return x<0? -1:1;
 42 }
 43 
 44 bool operator == (const Point& a, const Point& b){
 45     return (dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0);
 46 }
 47 
 48 //向量基本运算
 49 double Dot(Vector A, Vector B) {return A.x*B.x + A.y*B.y;}//点积
 50 double Length(Vector A) {return sqrt(Dot(A,A));}//自身乘积再开根号保证绝对值稳定性
 51 double Angle(Vector A, Vector B) {return acos(Dot(A,B)/Length(A)/Length(B));}
 52 
 53 //叉乘
 54 double Cross(Vector A, Vector B) {return A.x*B.y-A.y*B.x;}
 55 double Area2(Point A, Point B, Point C) {return Cross(B-A, C-A);}//相当于上面的为原点,为面积的两倍
 56 
 57 //角度转弧度
 58 double torad(double deg)
 59 {
 60     return deg/180*acos(-1);
 61 }
 62 //旋转
 63 Vector Rotate(Vector A, double rad) {
 64     return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
 65 }
 66 
 67 //单位法线
 68 Vector Normal(Vector A){
 69     double L = Length(A);
 70     return Vector(-A.y/L,A.x/L);
 71 }
 72 
 73 //点和直线
 74 
 75 //两条直线的交点
 76 //一条直线可以写成一个点和一个向量(方向)
 77 //
 78 Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){
 79     Vector u = P-Q;
 80     double t = Cross(w,u)/Cross(v,w);
 81     return P+v*t;
 82 }
 83 
 84 //点到直线的距离
 85 double DistanceToLine(Point P, Point A, Point B){
 86     Vector v1=B-A, v2=P-A;
 87     return fabs(Cross(v1,v2))/Length(v1); //如果不取绝对值,得到的是有向距离
 88 }
 89 
 90 //点到线段的距离
 91 double DistanceToSegment(Point P, Point A, Point B){
 92     if(A==B) return Length(P-A);
 93     Vector v1=B-A, v2=P-A, v3=P-B;
 94     //投影不在线段上的情况
 95     if(dcmp(Dot(v1,v2))<0) return Length(v2); //P在靠A侧
 96     else if(dcmp(Dot(v1,v3))>0) return Length(v3); //在靠近B的一侧
 97     else return fabs(Cross(v1,v2))/Length(v1);
 98 }
 99 
100 //点在直线上的投影
101 Point GetLineProjection(Point P, Point A, Point B){
102     Vector v=B-A;
103     return A+v*(Dot(v,P-A)/Dot(v,v)); //从A移动到投影
104 }
105 
106 //线段相交判定 相交为1 (交点不为端点)
107 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2){
108     double c1 = Cross(a2-a1,b1-a1);
109     double c2 = Cross(a2-a1,b2-a1);
110     double c3 = Cross(b2-b1,a1-b1);
111     double c4 = Cross(b2-b1,a2-b1);
112     return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
113 }
114 //判断一个点是否在一条线段上(用于判断一个端点是否在另一个线段上)
115 //如果c1 c2窦唯0,则线段共线
116 bool OnSegment(Point p, Point a1, Point a2){
117     return dcmp(Cross(a1-p, a2-p))==0 && dcmp(Dot(a1-p, a2-p))<0;
118 }
119 
120 //与圆和球有关的计算问题
121 
122 struct Line{
123     Point p;//线上一点
124     Vector v;//方向向量
125     double ang; //极角,从x正半轴旋转到v所需要的角(弧度)
126     Line(Point p, Vector v):p(p),v(v){ang = atan2(v.y,v.x);}
127     Point point(double t){return p+v*t;};
128     bool operator < (const Line& L) const{ //排序用的比较运算符
129         return ang < L.ang;
130     }
131 };
132 
133 struct Circle{
134     Point c;
135     double r;
136     Circle(Point c, double r):c(c),r(r){}
137     Point point(double a){ //通过圆心角求坐标的函数
138         return Point(c.x+cos(a)*r,c.y+sin(a)*r);
139     }
140 };
141 
142 //直线与圆的交点
143 //sol存放的是交点本身,代码没有清空sol,就很方便:可以反复调用把所有交点放在一个sol里
144 int getLineCircleIntersection(Line L, Circle C, double& t1, double& t2, vector<Point>& sol){
145     double a=L.v.x, b=L.p.x-C.c.x, c=L.v.y, d=L.p.y-C.c.y;
146     double e=a*a+c*c, f=2*(a*b+c*d), g=b*b+d*d-C.r*C.r;
147     double delta = f*f - 4*e*g;//判别式
148     if(dcmp(delta)<0) return 0; //相离
149     if(dcmp(delta)==0){
150         t1=t2=-f/(2*e);
151         sol.push_back(L.point(t1));
152         return 1;
153     }
154     //相交
155     t1 = (-f-sqrt(delta))/(2*e);
156     sol.push_back(L.point(t1));
157     t2 = (-f+sqrt(delta))/(2*e);
158     sol.push_back(L.point(t2));
159     return 2;
160 }
161 
162 //计算向量极角
163 double angle(Vector v){return atan2(v.y,v.x);}
164 
165 //两圆相交
166 int getCircleCircleIntersection(Circle C1, Circle C2, vector<Point>& sol){
167     double d=Length(C1.c-C2.c);
168     if(dcmp(d)==0){
169         if(dcmp(C1.r-C2.r)==0) return -1; //两圆重合
170         return 0;
171     }
172     if(dcmp(C1.r+C2.r-d)<0) return 0; //内含
173     if(dcmp(fabs(C1.r-C2.r)-d)>0) return 0; //外离
174     
175     double a = angle(C2.c-C1.c); //向量C1C2的极角
176     double da = acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));
177     //C1C2到C1P1的角
178     Point p1 = C1.point(a-da), p2 = C1.point(a+da);
179     
180     sol.push_back(p1);
181     if(p1==p2)return 1;
182     sol.push_back(p2);
183     return 2;
184 }
185 
186 //过定点作圆切线,v[i]是第i条切线,返回切线条数
187 int getTangents(Point p, Circle C, Vector* v){
188     Vector u = C.c-p;
189     double dist = Length(u);
190     if(dist<C.r) return 0;
191     else if(dcmp(dist-C.r)==0){ //p在圆上,只有一条切线
192         v[0]=Rotate(u,M_PI/2);
193         return 1;
194     }
195     else{
196         double ang = asin(C.r/dist);
197         v[0] = Rotate(u, -ang);
198         v[1] = Rotate(u, +ang);
199         return 2;
200     }
201 }
202 
203 //两圆的公切线
204 int getTangents(Circle A, Circle B, Point* a, Point* b){
205     int cnt=0;
206     if(A.r<B.r){
207         swap(A,B);
208         swap(a,b);
209     }
210     int d2=(A.c.x-B.c.x)*(A.c.x-B.c.x)+(A.c.y-B.c.y)*(A.c.y-B.c.y);
211     int rdiff=A.r-B.r;
212     int rsum=A.r+B.r;
213     if(d2<rdiff*rdiff) return 0; //内含
214     double base = atan2(B.c.y-A.c.y,B.c.x-A.c.x);
215     if(d2==0&&A.r==B.r) return -1; //无限多条切线
216     if(d2==rdiff*rdiff){//内切,一条切线
217         a[cnt]=A.point(base);
218         b[cnt]=B.point(base);
219         cnt++;
220         return 1;
221     }
222     //有外共切线
223     double ang = acos(A.r-B.r)/sqrt(d2);
224     a[cnt] = A.point(base+ang);
225     b[cnt] = B.point(base+ang);
226     cnt++;
227     a[cnt] = A.point(base+ang);
228     b[cnt] = B.point(base-ang);
229     cnt++;
230     if(d2==rsum*rsum){
231         a[cnt]=A.point(base);
232         b[cnt]=B.point(M_PI+base);
233         cnt++;
234     }
235     else if(d2>rsum*rsum){
236         double ang=acos((A.r+B.r)/sqrt(d2));
237         a[cnt]=A.point(base+ang);
238         b[cnt]=B.point(M_PI+base+ang);
239         cnt++;
240         a[cnt]=A.point(base-ang);
241         b[cnt]=B.point(M_PI+base-ang);
242         cnt++;
243     }
244     return cnt;
245 }
246 
247 //三角形外接圆(三点保证不共线)
248 Circle CircumscribedCircle(Point p1, Point p2, Point p3){
249     double Bx = p2.x-p1.x, By = p2.y-p1.y;
250     double Cx = p3.x-p1.x, Cy = p3.y-p1.y;
251     double D = 2*(Bx*Cy-By*Cx);
252     double cx = (Cy*(Bx*Bx+By*By)-By*(Cx*Cx+Cy*Cy))/D+p1.x;
253     double cy = (Bx*(Cx*Cx+Cy*Cy)-Cx*(Bx*Bx+By*By))/D+p1.y;
254     Point p = Point(cx,cy);
255     return Circle(p,Length(p1-p));
256 }
257 //三角形内切圆
258 Circle InscribedCircle(Point p1, Point p2, Point p3){
259     double a = Length(p2-p3);
260     double b = Length(p3-p1);
261     double c = Length(p1-p2);
262     Point p = (p1*a+p2*b+p3*c)/(a+b+c);
263     return Circle(p, DistanceToLine(p, p1, p2));
264 }
265 
266 
267 //二维几何常用算法
268 typedef vector<Point> Polygon;
269 //多边形的有向面积
270 double PolygonArea(Polygon po) {
271     int n = po.size();
272     double area = 0.0;
273     for(int i = 1; i < n-1; i++) {
274         area += Cross(po[i]-po[0], po[i+1]-po[0]);
275     }
276     return area * 0.5;
277 }
278 
279 //点在多边形内判定
280 int isPointInPolygon(Point p, Polygon poly){
281     int wn = 0; //绕数
282     int n = poly.size();
283     for(int i=0;i<n;i++){
284         if(OnSegment(p,poly[i],poly[(i+1)%n])) return -1;//边界上
285         int k = dcmp(Cross(poly[(i+1)%n]-poly[i], p-poly[i]));
286         int d1 = dcmp(poly[i].y-p.y);
287         int d2 = dcmp(poly[(i+1)%n].y-p.y);
288         if(k>0&&d1<=0&&d2>0) wn++;
289         if(k<0&&d2<=0&&d1>0) wn--;
290     }
291     if(wn!=0) return 1;//内部
292     return 0;//外部
293 }
294 
295 //凸包
296 //Andrew算法
297 bool myCmp(Point A, Point B)
298 {
299     if(A.x != B.x)    return A.x < B.x;
300     else return A.y < B.y;
301 }
302 
303 int ConvexHall (Point* p, int n, Point* ch){
304     sort(p,p+n,myCmp); //先比较x坐标,再比较y坐标
305     int m = 0;
306     for(int i=0;i<n;i++){
307         while(m>1&&Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])<=0) m--;
308         ch[m++] = p[i];
309     }
310     if(n>1)m--;
311     return m;
312 }
View Code
double PolygonArea(Point *p,int n)
{
    double area=0;
    for(int i=1;i<n-1;i++)
        area += Cross(p[i]-p[0],p[i+1]-p[0]);
    return fabs(area)/2;
}
int ConvexHull(Point *p,int n,Point *ch)
{
    sort(p,p+n);
    n=unique(p,p+n)-p;
    int m=0;
    for(int i=0;i<n;i++)
    {
        while(m>1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])<=0) m--;
        ch[m++]=p[i];
    }
    int k=m;
    for(int i=n-2;i>=0;i--)
    {
        while(m>k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])<=0) m--;
        ch[m++]=p[i];
    }
    if(n>1) m--;
    return m;
}

 

转载于:https://www.cnblogs.com/cmbyn/p/8860985.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM 很全的计算几何模板 基础部分 1.几何公式 5 1.1三角形 5 1.2四边形 5 1.3正n边形 5 1.4圆 5 1.5棱柱 6 1.6棱锥 6 1.7棱台 6 1.8圆柱 6 1.9圆锥 6 1.10圆台 7 1.11球 7 1.12球台 7 1.13球扇形 7 2.直线与线段 7 2.0预备函数 7 2.1判三点是否共线 8 2.2判点是否在线段上 9 2.3判断两点在线段的同一侧 9 2.4判断两点是否在线段的异侧 9 2.5求点关于直线的对称点 10 2.7判断两线段是否相交 10 2.7.1常用版 10 2.7.2不常用版 11 2.8 求两条直线的交点 11 2.9点到直线的最近距离 12 2.10点到线段的最近距离 12 3.多边形 12 3.0 预备浮点函数 12 3.1判定是否是凸多边形 13 3.2判定点是否在多边形内 14 3.3 判定一条线段是否在一个任意多边形内 15 4. 三角形 16 4.0预备函数 16 4.1求三角形的外心 17 4.2求三角形内心 17 4.3求三角形垂心 17 5. 圆 18 5.0预备函数 18 5.1判定直线是否与圆相交 19 5.2判定线段与圆相交 19 5.3判圆和圆相交 19 5.4计算圆上到点p最近点 19 5.5计算直线与圆的交点 20 5.6计算两个圆的交点 20 6. 球面 21 6.0给出地球经度纬度,计算圆心角 21 6.1已知经纬度,计算地球上两点直线距离 21 6.2已知经纬度,计算地球上两点球面距离 21 7. 三维几何的若干模板 22 7.0预备函数 22 7.1判定三点是否共线 23 7.2判定四点是否共面 23 7.1判定点是否在线段上 23 7.2判断点是否在空间三角形上 24 7.3判断两点是否在线段同侧 24 7.4判断两点是否在线段异侧 25 7.5判断两点是否在平面同侧 25 7.6判断两点是否在平面异侧 25 7.7判断两空间直线是否平行 25 7.8判断两平面是否平行 26 7.9判断直线是否与平面平行 26 7.10判断两直线是否垂直 26 7.11判断两平面是否垂直 26 7.12判断两条空间线段是否相交 27 7.13判断线段是否与空间三角形相交 27 7.14计算两条直线的交点 28 7.15计算直线与平面的交点 28 7.16计算两平面的交线 29 7.17点到直线的距离 29 7.18 计算点到平面的距离 29 7.19计算直线到直线的距离 30 7.20空间两直线夹角的cos值 30 7.21两平面夹角的cos值 30 7.22直线与平面夹角sin值 31 1.最远曼哈顿距离 31 2. 最近点对 32 3. 最近点对 34 4. 最小包围圆 36 5. 求两个圆的交点 39 6. 求三角形外接圆圆心 40 7. 求凸包 42 8.凸包卡壳旋转求出所有对踵点、最远点对 44 9. 凸包+旋转卡壳求平面面积最大三角 47 10. Pick定理 50 11. 求多边形面积和重心 51 12. 判断一个简单多边形是否有核 52 13. 模拟退火 54 14. 六边形坐标系 56 15. 用一个给定半径的圆覆盖最多的点 60 16. 不等大的圆的圆弧表示 62 17. 矩形面积并 62 18. 矩形的周长并 66 19. 最近圆对 70 20. 求两个圆的面积交 74

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值