计算几何模板

发布时间 2023-08-08 17:47:29作者: Rolling_star
namespace ComputationGeometry{
    const ld eps=1e-8,pi=acosl(-1.0);
    // 点 / 向量
    struct vec{
        ld x,y;
        vec(ld X=0,ld Y=0){x=X;y=Y;}
        // 输入输出
        void in(){scanf("%Lf%Lf",&x,&y);}
        void out(){printf("%Lf %Lf\n",x,y);}
        // 加减数乘
        vec operator +(vec a){return (vec){x+a.x,y+a.y};}
        vec operator -(vec a){return (vec){x-a.x,y-a.y};}
        vec operator *(ld a){return (vec){x*a,y*a};}
        vec operator /(ld a){return (vec){x/a,y/a};}
        // 旋转 / 绕某一点旋转
        vec rotate(ld t){return (vec){x*cosl(t)+y*sinl(t),-x*sinl(t)+y*cosl(t)};}
        vec rotate(vec a,ld t){return (vec){(x-a.x)*cosl(t)+(y-a.y)*sinl(t)+a.x,-(x-a.x)*sinl(t)+(y-a.y)*cosl(t)+a.y};}
        // 相等
        bool operator ==(vec a){return (fabsl(x-a.x)<eps)&(fabsl(y-a.y)<eps);}
        // 叉乘 / 点乘
        ld operator *(vec a){return x*a.y-y*a.x;}
        ld operator ^(vec a){return x*a.x+y*a.y;}
        ld len(){return sqrtl(x*x+y*y);}
    };
    // 两点斜率
    ld slope(vec a,vec b){return (a.y-b.y)/(a.x-b.x);}
    // 直线 / 线段
    struct line{
        vec p1,p2;
        // 直线斜率
        ld slope(){return (p1.y-p2.y)/(p1.x-p2.x);}
        // 已知 x 求 y
        ld val_y(ld x){
            int k=slope(),b=p1.y-p1.x*k;
            return k*x+b;
        }
        // 已知 y 求 x
        ld val_x(ld y){
            int k=slope(),b=p1.y-p1.x*k;
            return (y-b)/k;
        }
    };
    // 两点之间距离
    inline ld dis(vec a,vec b){return (a-b).len();}
    // 点与直线之间距离
    inline ld dis_line(vec p,line a){return fabsl((p-a.p1)*(a.p2-a.p1)/((a.p1-a.p2).len()));}
    // 点是否在直线上
    bool pip_line(vec p,line a){return dis_line(p,a)<eps;}
    // 两线段是否相交
    bool cross(line a,line b){
        ld t1=(a.p2-a.p1)*(b.p1-a.p1),t2=(a.p2-a.p1)*(b.p2-a.p1);
        ld t3=(b.p2-b.p1)*(a.p1-b.p1),t4=(b.p2-b.p1)*(a.p2-b.p1);
        return (t1*t2<eps)&(t3*t4<eps);
    }
    // 两直线交点
    vec p_cross(line a,line b){
        vec x=a.p2-a.p1,y=b.p2-b.p1,z=a.p1-b.p1;
        return a.p1+x*((y*z)/(x*y));
    }
    bool cmp(vec a,vec b){
        if(a.x==b.x) return a.y<b.y;
        else return a.x<b.x;
    }
    // 二维凸包
    void Convex(vec in[],vec out[],int &cnt){
        int stk[N],top=0;bool vis[N];
        sort(in+1,in+1+cnt,cmp);
        stk[top=1]=1;
        for(int i=2;i<=cnt;i++){
            while(top>=2&&(in[i]-in[stk[top]])*(in[stk[top]]-in[stk[top-1]])<eps) vis[stk[top--]]=false;
            vis[i]=true;stk[++top]=i;
        }
        int siz=top;
        for(int i=cnt-1;i>=1;i--){
            if(vis[i]) continue;
            while(top>siz&&(in[i]-in[stk[top]])*(in[stk[top]]-in[stk[top-1]])<eps) vis[stk[top--]]=false;
            vis[i]=true;stk[++top]=i;
        }
        for(int i=1;i<=top;i++) out[i]=in[stk[i]]; cnt=top;
    }
}
using namespace ComputationGeometry;