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


    //
    //  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;
    }
  • 相关阅读:
    Rust入坑指南:亡羊补牢
    antirez:Redis6真的来了
    代码检查又一利器:ArchUnit
    【译】浅谈SOLID原则
    Rust入坑指南:鳞次栉比
    【译】什么才是优秀的代码
    Elasticsearch从入门到放弃:文档CRUD要牢记
    【译】利用Lombok消除重复代码
    Netty 中的心跳检测机制
    Netty 中的异步编程 Future 和 Promise
  • 原文地址:https://www.cnblogs.com/cmbyn/p/8860985.html
Copyright © 2020-2023  润新知