计算几何模版

const double eps=1e-8;

int dcmp(double x){
    if (fabs(x)<eps) {
        return 0;
    }
    else return x<0?-1:1;
}

struct Point{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y){}
    int in(){
        return scanf("%lf%lf",&x,&y);
    }
};

typedef Point Vector;

struct Circle{
    Point c;
    double r;
    Circle(){}
    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);
    }
    
    void in(){
        c.in();
        scanf("%lf",&r);
    }
    
};


inline Vector operator+ (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }
inline Vector operator- (Point A, Point B) { return Vector(A.x - B.x, A.y - B.y); }
inline Vector operator* (Vector A, double p) { return Vector(A.x * p, A.y * p); }
inline Vector operator/ (Vector A, double p) { return Vector(A.x / p, A.y / p); }
inline bool operator < (Point a, Point b) { return a.x < b.x || (a.x == b.x && a.y < b.y); }
inline bool operator == (Point a, Point b) { return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0; }

inline long double Dot(Vector A, Vector B){ return A.x * B.x + A.y * B.y;}

inline long double Length(Vector A) { return sqrt(Dot(A, A)); }

inline Vector Unit(Vector x) { return x / Length(x); }  //单位向量

inline double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); }

inline double angle(Vector v) { return atan2(v.y, v.x); }

inline long double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }

inline bool OnSegment(Point p, Point a1, Point a2)//包括端点
{
    return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) <= 0;
}

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

Vector Rotate(Vector A,double rad){   //旋转
    return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}


struct Line{
    Point p;
    Vector v;
    double ang;
    Line(){}
    Line(Point p,Vector v):p(p),v(v){
        ang=atan2(v.y, v.x);
    }
    inline Point point(double t)
    {
        return p + v * t;
    }
    bool operator <(Line a) const{
        return ang<a.ang;
    }
};

//三边构成三角形的判定
bool check_length(double a, double b, double c) {  
    return dcmp(a+b-c) > 0 && dcmp(fabs(a-b)-c) < 0;  
}  
bool isTriangle(double a, double b, double c) {  
    return check_length(a, b, c) && check_length(a, c, b) && check_length(b, c, a);  
}

//平行四边形的判定(保证四边形顶点按顺序给出)  
bool isParallelogram(Point  *p) {  
    if (dcmp(Length(p[0]-p[1]) - Length(p[2]-p[3])) || dcmp(Length(p[0]-p[3]) - Length(p[2]-p[1]))) return false;       
    Line a = Line(p[0], p[1]-p[0]);  
    Line b = Line(p[1], p[2]-p[1]);  
    Line c = Line(p[3], p[2]-p[3]);  
    Line d = Line(p[0], p[3]-p[0]);  
    return dcmp(a.ang - c.ang) == 0 && dcmp(b.ang - d.ang) == 0;  
}

//梯形的判定  顺序输入
bool isTrapezium(Point *p) {  
    Line a = Line(p[0], p[1]-p[0]);  
    Line b = Line(p[1], p[2]-p[1]);  
    Line c = Line(p[3], p[2]-p[3]);  
    Line d = Line(p[0], p[3]-p[0]);  
    return (dcmp(a.ang - c.ang) == 0 && dcmp(b.ang - d.ang)) || (dcmp(a.ang - c.ang) && dcmp(b.ang - d.ang) == 0);  
} 
//菱形的判定  顺序输入
bool isRhombus(Point *p) {  
    if (!isParallelogram(p)) return false;  
    return dcmp(Length(p[1]-p[0]) - Length(p[2]-p[1])) == 0;  
} 
//矩形的判定  
bool isRectangle(Point *p) {  
    if (!isParallelogram(p)) return false;  
    return dcmp(Length(p[2]-p[0]) - Length(p[3]-p[1])) == 0;  
}  

//正方形的判定  
bool isSquare(Point *p) {  
    return isRectangle(p) && isRhombus(p);  
}  
   
//三点共线的判定  
bool isCollinear(Point A, Point B, Point C) {  
    return dcmp(Cross(B-A, C-B)) == 0;  
} 

//点在多边形内的判定(多边形顶点需按逆时针排列)  
bool isInPolygon(Point p,Point *poly,int n) {  
    for(int i = 0; i < n; i++) {  
        //若允许点在多边形边上,可关闭下行注释  
        // if (isOnSegment(p, poly[(i+1)%n], poly[i])) return true;  
        if (Cross(poly[(i+1)%n]-poly[i], p-poly[i]) < 0) return false;  
    }  
    return true;  
}

//过定点作圆的切线  
int getTangents(Point P, Circle C, Line *L,int &n) {  
    Vector u = C.c - P;  
    double dis = Length(u);  
    if (dcmp(dis - C.r) < 0) return 0;  
    if (dcmp(dis - C.r) == 0) {  
        L[n++]={P, Rotate(u, pi / 2.0)};  
        return 1;  
    }  
    double ang = asin(C.r / dis);  
    L[n++]=Line(P, Rotate(u, ang));  
    L[n++]=Line(P, Rotate(u, -ang));  
    return 2;  
} 

//两圆位置关系判定  
int GetCircleLocationRelation(Circle A, Circle B){ 
    double d = Length(A.c-B.c);  
    double sum = A.r + B.r;  
    double sub = fabs(A.r - B.r);  
    if (dcmp(d) == 0) return dcmp(sub) != 0;  
    if (dcmp(d - sum) > 0) return 2;//XiangLi;  
    if (dcmp(d - sum) == 0) return 1;//WaiQie;  
    if (dcmp(d - sub) > 0 && dcmp(d - sum) < 0) return 0;//INTERSECTING;  
    if (dcmp(d - sub) == 0) return -1;//NeiQie;  
    if (dcmp(d - sub) < 0) return -2;//NeiHan;  
}

//两圆相交的面积
double GetCircleIntersectionArea(Circle A, Circle B) {
    int rel = GetCircleLocationRelation(A, B);
    if (rel < 0/*INTERSECTING*/) return min(A.r*A.r*pi, B.r*B.r*pi);
    if (rel > 0/*INTERSECTING*/) return 0;
    double dis = Length(A.c - B.c);
    double ang1 = acos((A.r*A.r + dis*dis - B.r*B.r) / (2.0*A.r*dis));
    double ang2 = acos((B.r*B.r + dis*dis - A.r*A.r) / (2.0*B.r*dis));
    return ang1*A.r*A.r + ang2*B.r*B.r - A.r*dis*sin(ang1); 
}

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

inline Point getmiorr(Point P,Line a){
    Point pp=GetLineProjection(P,a.p,a.p+a.v);
    return pp*2-P;
}


inline bool Seg_inter_Line(Line l1,Point a,Point b){//判断直线l1 是否相交线段ab
    return dcmp(Cross(l1.p-a,l1.p-a+l1.v))*dcmp(Cross(l1.p-b, l1.p+l1.v-b))<=0;
}

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

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

long 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);
    else if(dcmp(Dot(v1, v3))>0) return Length(v3);
    else return fabs(Cross(v1, v2))/Length(v1);
}

bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2){ //线段相交
    double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1, b2-a1),c3=Cross(b2-b1, a1-b1),c4=Cross(b2-b1, a2-b1);
    return dcmp(c1)*dcmp(c2)<=0&&dcmp(c3)*dcmp(c4)<=0;
}

//二维凸包
int n,res[maxn],top;

bool cmp(Point a,Point b){
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.x;
}

int Cross(Point a,Point b){
    return a.x*b.y-a.y*b.x;
}

void ConvexHull(){
    int len;
    top=0;
    sort(p,p+n,cmp);
    for(int i=0;i<n;i++){
        while(top>1&&Cross(p[res[top-1]]-p[res[top-2]],p[i]-p[res[top-2]])<=0)
            top--;
        res[top++]=i;
    }
    len=top;
    for(int i=n-2;i>=0;i--){
        while(top>len&&Cross(p[res[top-1]]-p[res[top-2]],p[i]-p[res[top-2]])<=0)top--;
        res[top++]=i;
    }
    if(n>1)--top;
    //  cout<<top<<endl;
}

// 半平面交
bool OnLeft(Line L,Point p){
    return Cross(L.v, p-L.p)>0;
}

Point GetIntersection(Line a,Line b){
    Vector u=a.p-b.p;
    double t=Cross(b.v, u)/Cross(a.v, b.v);
    return a.p+a.v*t;
}

double ConvexPolygonArea(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 area/2;
}
//左上角 逆时针平面
int HalfplaneIntersection(Line *L,int n,Point *poly){
    sort(L, L+n);
    int first,last;
    Point *p=new Point[n];
    Line *q=new Line[n];
    q[first=last=0]=L[0];
    for (int i=1; i<n; ++i) {
        while (first<last&&!OnLeft(L[i], p[last-1])) {
            last--;
        }
        while (first<last&&!OnLeft(L[i], p[first])) {
            first++;
        }
        q[++last]=L[i];
        if(fabs(Cross(q[last].v,q[last-1].v))<eps) {
            --last;
            if(OnLeft(q[last], L[i].p))
                q[last]=L[i];
        }
        if (first<last)
            p[last-1]=GetIntersection(q[last-1], q[last]);
    }
    while (first<last&&!OnLeft(q[first], p[last-1])) {
        --last;
    }
    if (last-first<=1) {
        return 0;
    }
    p[last]=GetIntersection(q[last], q[first]);
    int m=0;
    for (int i=first; i<=last; ++i) {
        poly[m++]=p[i];
    }
    delete []p;
    delete []q;
    return m;
}

double Rotation_Calipers(int len){      //旋转卡壳求凸包最大三角形

    double ans = 0;
    for(int i = 0 ; i < len ; i++){
        int j = (i + 1) % len;
        int k = (j + 1) % len;
        while(j != i && k != i){
            while(dcmp(fabs(Cross(p[j]-p[i],p[(k+1)%len]-p[i])) - fabs(Cross(p[j]-p[i],p[k]-p[i])))>0)
                k = (k + 1) % len;
            ans = max(ans,fabs(Cross(p[j]-p[i],p[k]-p[i])));
            // 最大 三个点 i,j,k
            j = (j + 1) % len;
        }
    }
    return ans;
}
// 求凸包 最远点对
double dis(Point a, Point b)
{
    return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}

double rotating_calipers(Point *p, int n)///旋转卡壳求凸包的直径,平面最远的点对
{
    int k=1;
    double ans = 0;
    p[n]=p[0];
    for(int i=0; i<n; i++)
    {
        while(fabs(Cross(p[i+1]-p[i],p[k]-p[i]))<fabs(Cross(p[i+1]-p[i],p[k+1]-p[i])))
            k=(k+1)%n;
        ans = max(ans,max(dis(p[i],p[k]),dis(p[i+1],p[k])));///注意是用的函数dis
    }
    return ans;
}

//定圆覆盖最大点数
struct alpha
{
    double v;
    bool flag;
    bool operator < (alpha b) const //排序专用偏序关系
    {
        return v < b.v;
    }
} alp[Mn * Mn + 5]; //C(N,2)*2的可能交点(可能极角)


double dis(Point a,Point b)
{
    return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}

double R;//定长

int solve(int n)
{
    int MAX = 0;
    for(int i = 0; i < n; i++)
    {
        int t = 0;
        for(int j = 0; j < n; j++)
        {
            if(i == j)
                continue;
            double theta,phi,D;
            D = dis(p[i],p[j]);
            if(D > 2.0 * R)
                continue;
            theta = atan2(p[j].y - p[i].y,p[j].x - p[i].x);
            if(theta < 0)
                theta += 2 * pi;
            phi = acos(D / (2.0 * R));
            alp[t].v = theta - phi + 2 * pi;
            alp[t].flag = true;
            alp[t + 1].v = theta + phi + 2 * pi;
            alp[t + 1].flag = false;
            t += 2;
        }
        sort(alp,alp + t);
        int sum = 0;
        for(int j = 0; j < t; j++)
        {
            if(alp[j].flag)
                sum ++;
            else
                sum --;
            if(sum > MAX)
                MAX = sum;
        }
    }
    return MAX+1;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值