几何模板
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(); }