几何模板

const double PI = acos(-1);

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

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

typedef Point Vector;

struct Circle {
    Point c;
    double r;
    Circle(Point c = Point(0, 0), double r = 0):c(c),r(r){}
    Point getPoint(double rad) {
        return Point(cos(rad) * r + c.x, sin(rad) * r + c.y);
    }
};

Point operator + (Vector A, Vector B) {return Point(A.x + B.x, A.y + B.y);}
Point operator - (Vector A, Vector B) {return Point(A.x - B.x, A.y - B.y);}
Point operator * (Vector A, double p) {return Point(A.x * p, A.y * p);}
Point operator / (Vector A, double p) {return Point(A.x / p, A.y / p);}
bool operator < (const Vector &A, const Vector &B) {return A.x < B.x || (A.x == B.x && A.y < B.y);}
bool operator == (const Vector &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);}

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

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

//凸包
int ConvexHull(Point *p, int n, Point *ch) {
    sort(p, p + n);
    int m = 0;
    for(int i = 0; i < n; i++) {
        while(m > 1 && dcmp(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 && dcmp(Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2])) <= 0) m--;
        ch[m++] = p[i];
    }
    return m;
}

//两圆共切线
int getTangents(Circle A, Circle B, vector<Point>& a, vector<Point>& b) { 
    if(A.r < B.r) swap(A, B), swap(a, b);
    double 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);
    double rdiff = A.r - B.r;
    double rsum = A.r + B.r;
    if(dcmp(d2 - rdiff * rdiff) < 0) return 0;
    double base = atan2(B.c.y-A.c.y,B.c.x-A.c.x);
    if(d2 == 0 && dcmp(A.r - B.r) == 0) return -1;
    if(dcmp(d2 - rdiff * rdiff) == 0) {
        a.push_back(A.getPoint(base));
        b.push_back(B.getPoint(base));
        return 1;
    }
    //有公切线
    double ang = acos((A.r - B.r) / sqrt(d2));
    a.push_back(A.getPoint(base+ang)); b.push_back(B.getPoint(base+ang));
    a.push_back(A.getPoint(base-ang)); b.push_back(B.getPoint(base-ang));
    if(dcmp(d2 - rsum * rsum) == 0) {
        a.push_back(A.getPoint(base)); b.push_back(B.getPoint(PI+base));
    } else if(dcmp(d2 - rsum * rsum) > 0) {
        double ang = acos((A.r + B.r) / sqrt(d2));
        a.push_back(A.getPoint(base+ang)); b.push_back(B.getPoint(PI+base+ang));
        a.push_back(A.getPoint(base-ang)); b.push_back(B.getPoint(PI+base-ang));
    }
    return (int)a.size();
}
原文地址:https://www.cnblogs.com/CJLHY/p/10464967.html