My Geometry Template 2D(Updating...)

//Hello. I'm Peter.
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
#define peter cout<<"i am peter"<<endl
#define fuck(x) cerr << #x << " <- " << x << endl
typedef long long ll;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
/*--------------------------定量和定函数--------------------------*/
const double eps = 1e-9, pi = acos(-1.0);
inline const int sgn(double x){
    if(fabs(x) < eps) return 0;
    else return x > 0? 1 : -1;
}
inline const double sq(double x){return x*x;}


/*--------------------------向量--------------------------*/
struct Point{
    double x, y;
    Point(){};
    Point(double x1, double y1){x = x1, y = y1;}
};
typedef Point Vector;
Vector operator + (const Vector a, const Vector b){
    return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (const Vector a, const Vector b){
    return Vector(a.x - b.x, a.y - b.y);
}
double operator * (const Vector a, const Vector b){
    return a.x * b.x + a.y * b.y;
}
double operator % (const Vector a, const Vector b){
    return a.x * b.y - a.y * b.x;
}
Vector operator * (const Vector a, const double b){
    return Vector(a.x * b, a.y * b);
}
Vector operator * (const double b, const Vector a){
    return Vector(a.x * b, a.y * b);
}
Vector operator / (const Vector a, const double b){
    return Vector(a.x / b, a.y / b);
}
bool operator == (const Point a, const Point b){
    return sgn(a.x - b.x)==0 && sgn(a.y - b.y)==0;
}
bool operator || (const Vector a, const Vector b){
    return sgn(a % b)==0;
}
bool operator / (const Vector a, const Vector b){
    return sgn(a % b)!=0;
}
double Length(Vector v){
    return (double)sqrt((double)(v.x * v.x + v.y * v.y));
}
double LenSq(Vector v){
    return v.x*v.x + v.y*v.y;
}
double Dis(Point a, Point b){
    return Length(a - b);
}
Vector Rotate(Vector v, double rad){
    return Vector(v.x * cos(rad) - v.y * sin(rad), v.x * sin(rad) + v.y * cos(rad));
}
Vector Norv(Vector v){
    return Vector(v.y, -v.x);
}
Vector Unitv(Vector v){
    return v / Length(v);
}
double angle(Vector v){
    return atan2(v.y, v.x);
}
double angle(Vector a, Vector b){
    double ans = angle(a) - angle(b);
    while(sgn(ans) < 0) ans += 2*pi; while(sgn(ans - 2*pi) >= 0) ans -= 2*pi;
    return fmin(ans, 2*pi - ans);
}

//以下是排序和去重使用的比较函数
bool cmpxy(const Point a, const Point b){
    if(sgn(a.x-b.x)) return a.x < b.x;
    else return a.y < b.y;
}
bool cmpyx(const Point a, const Point b){
    if(sgn(a.y-b.y)) return a.y < b.y;
    else return a.x < b.x;
}
bool cmpYx(const Point a, const Point b){
    if(sgn(a.y-b.y)) return a.y > b.y;
    else return a.x < b.x;
}
bool cmpyX(const Point a, const Point b){
    if(sgn(a.y-b.y)) return a.y < b.y;
    else return a.x > b.x;
}
bool cmpeq(const Point a, const Point b){
    return a==b;
}
//以上是排序和去重使用的比较函数


/*--------------------------直线--------------------------*/
struct Line{
    Point p; Vector v;
    Line(){};
    Line(Point p1, Vector v1){p = p1, v = v1;}
};
Point operator / (const Line a, const Line b){
    double t = ((b.p - a.p) % b.v) / (a.v % b.v);
    return a.p + a.v * t;
}
double Dis(Point p, Line l){
    return fabs(l.v % (p - l.p)) / Length(l.v);
}
double angle(Line a, Line b){
    double ans = angle(a.v, b.v);
    return fmin(ans, pi - ans);
}
double angle(Line l){
    //求直线和x轴正方向的夹角,范围[0, pi)
    double a = angle(Vector(1, 0), l.v);
    if(Rotate(Vector(1, 0), a) / l.v) a = pi - a;
    return a;
}


/*--------------------------射线--------------------------*/
typedef Line Ray;


/*--------------------------线段--------------------------*/
struct Seg{
    Point p1, p2;
    Seg(){};
    Seg(Point p11, Point p22){p1 = p11, p2 = p22;}
};
bool PointOnSeg(Point p, Seg s){
    if((s.p1 - p) / (s.p2 - p)) return false;
    else if(sgn((s.p1 - p) * (s.p2 - p)) > 0) return false;
    else return true;
}
bool operator / (const Seg a, const Seg b){//此函数容易写错,且不同题目需要修改,特别注意
    if((a.p2 - a.p1) || (b.p2 - b.p1)){
        return PointOnSeg(a.p1, b) || PointOnSeg(a.p2, b) ||
        PointOnSeg(b.p1, a) || PointOnSeg(b.p2, a);
    }
    else return sgn((a.p2 - a.p1) % (b.p1 - a.p1)) * sgn((a.p2 - a.p1) % (b.p2 - a.p1)) <= 0 &&
        sgn((b.p2 - b.p1) % (a.p1 - b.p1)) * sgn((b.p2 - b.p1) % (a.p2 - b.p1)) <= 0 ;
}
bool operator / (const Line a, const Seg b){
    return sgn(a.v % (b.p1 - a.p)) * sgn(a.v % (b.p2 - a.p)) <= 0;
}


/*--------------------------圆--------------------------*/
struct Circle{
    Point p;
    double r;
    Circle(){};
    Circle(Point p1, double r1){p = p1, r = r1;}
    Point point(double rad){
        return Point(p.x + r * cos(rad), p.y + r * sin(rad));
    }
};
//以下几个位置关系函数,有些题目重新书写会更好
bool InTan(const Circle c1, const Circle c2){//内切
    return sgn(Dis(c1.p, c2.p) - fabs(c2.r - c1.r)) == 0;//两圆顺序无关
}
bool In(const Circle c1, const Circle c2){//内含
    return sgn(Dis(c1.p, c2.p) - fabs(c2.r - c1.r)) < 0;//两圆顺序无关
}
bool ExTan (const Circle c1, const Circle c2){//外切
    return sgn(Dis(c1.p, c2.p) - (c1.r + c2.r)) == 0;
}
bool Out(const Circle c1, const Circle c2){//外离
    return sgn(Dis(c1.p, c2.p) - (c1.r + c2.r)) > 0;
}
bool Inter(const Circle c1, const Circle c2){//相交
    return sgn(Dis(c1.p, c2.p) - fabs(c2.r - c1.r)) > 0 && sgn(Dis(c1.p, c2.p) - (c1.r + c2.r)) < 0;
}
//以上几个位置关系函数,有些题目重新书写会更好

bool PointOnCircle(Point p, Circle c){
    return sgn(Dis(p, c.p) - c.r) == 0;
}
bool PointInCircle(Point p, Circle c){
    return sgn(Dis(p, c.p) - c.r) < 0;
}
bool PointOnInCircle(Point p, Circle c){
    return sgn(Dis(p, c.p) - c.r) <= 0;
}
double Area_fan(Vector v1, Vector v2, double r){
    return 0.5 * angle(v1, v2) * r * r;
}
double Area_fan(double rad, double r){
    return 0.5 * rad * r * r;
}
void Tan_Circles_sub1(Circle c1, Circle c2, Line *l, int &nl){
    //第一种情况,求两圆两条外切线,前提是两圆相离或外切或相交
    if(!Out(c1, c2) && !ExTan(c1, c2) && !Inter(c1 ,c2)) return;

    if(c1.r > c2.r) swap(c1, c2);//保证c1较小
    Vector v12 = c2.p - c1.p;
    double av = angle(v12);
    double b = c2.r - c1.r;
    double c = Dis(c1.p, c2.p);
    double a = acos(b/c);
    Point x11, x12, x21, x22;
    x11 = c1.point(av + a), x12 = c1.point(av - a);
    x21 = c2.point(av + a), x22 = c2.point(av - a);

    l[nl++] = Line(x11, x21 - x11), l[nl++] = Line(x12, x22 - x12);
}
void Tan_Circles_sub2(Circle c1, Circle c2, Line *l, int &nl){
    //第二种情况,求两圆两条内切线,前提是两圆相离
    if(!Out(c1, c2)) return;

    double dis = Dis(c1.p, c2.p);
    double d2 = dis / ((c1.r/c2.r) + 1);
    double d1 = dis - d2;

    double a1 = acos(c1.r / d1);
    Vector v12 = c2.p - c1.p;
    double av12 = angle(v12);
    Point x11, x12;
    x11 = c1.point(av12 + a1), x12 = c1.point(av12 - a1);

    double a2 = acos(c2.r / d2);
    Vector v21 = c1.p - c2.p;
    double av21 = angle(v21);
    Point x21, x22;
    x21 = c2.point(av21 + a2), x22 = c2.point(av21 - a2);

    l[nl++] = Line(x11, x21 - x11), l[nl++] = Line(x12, x22 - x12);
}
void Tan_Circles_sub3(Circle c1, Circle c2, Line *l, int &nl){
    //第三种情况,两圆外切时,求一条内切线
    if(!ExTan(c1, c2)) return;

    Vector v12 = c2.p - c1.p;
    Point x = c1.p + (Unitv(v12)*(c1.r));
    Vector norv = Norv(v12);

    l[nl++] = Line(x, norv);
}
void Tan_Circles_sub4(Circle c1, Circle c2, Line *l, int &nl){
    //第四种情况,两圆内切时,求切线
    if(!InTan(c1, c2)) return;

    if(c1.r < c2.r) swap(c1, c2);//保证c2比较小
    Vector v12 = c2.p - c1.p;
    Point x = c1.p + (Unitv(v12)*(c1.r));
    Vector norv = Norv(v12);

    l[nl++] = Line(x, norv);
}
void Tan_Circles(Circle c1, Circle c2, Line *l, int &nl){
    nl = 0;//这里经常需要修改,特别注意
    Tan_Circles_sub1(c1, c2, l, nl);
    Tan_Circles_sub2(c1, c2, l, nl);
    Tan_Circles_sub3(c1, c2, l, nl);
    Tan_Circles_sub4(c1, c2, l, nl);
}


/*--------------------------不同类相交--------------------------*/
void Point_LineInterCircle(Line l, Circle c, Point *x, int &nx){
    //直线和圆相交
    Vector v1 = l.p - c.p;
    double A = LenSq(l.v), B = 2 * l.v * v1, C = LenSq(v1) - sq(c.r);
    double delta = B*B - 4*A*C;

    nx = 0;//这里经常需要修改,特别注意
    if(sgn(delta) < 0) return;//这里经常需要修改,特别注意
    double t1, t2;
    t1 = (-B + (double)sqrt((double)delta)) / (2*A);
    t2 = (-B - (double)sqrt((double)delta)) / (2*A);
    x[nx++] = l.p + l.v * t1;
    if(sgn(delta) > 0) x[nx++] = l.p + l.v * t2;
}
void Point_SegInterCircle(Seg s, Circle c, Point *x, int &nx){
    //线段和圆相交
    Point x1[5];
    int nx1;
    Point_LineInterCircle(Line(s.p1, s.p2 - s.p1), c, x1, nx1);

    nx = 0;
    for(int i = 0; i < nx1; i++){
        if(PointOnSeg(x1[i], s)) x[nx++] = x1[i];
    }
}
void Point_RayInterCircle(Ray l, Circle c, Point *x, int &nx){
    //射线和圆相交
    Point x1[5]; int nx1 = 0;
    Point_LineInterCircle(l, c, x1, nx1);

    nx = 0;
    for(int i = 0; i < nx1; i++){
        if(sgn((x1[i] - l.p) * l.v) > 0) x[nx++] = x1[i];
    }
}
void Tan_PointCircle(Point p, Circle c, Line *l, int &nl){
    //求一个点到一个圆的两条切线,前提是该点不能在圆内

    if(PointInCircle(p, c)) return;

    nl = 0;//这里经常需要修改,特别注意
    if(PointOnCircle(p, c)){
        Vector v = Norv(p - c.p);
        l[nl++] = Line(p, v);
        //当求的是射线时,这里需要修改,特别注意
        return;
    }
    else{
        double a = asin(c.r / Dis(p, c.p));
        Vector v;

        v = Rotate(c.p - p, a);
        l[nl++] = Line(p, v);

        v = Rotate(c.p - p, -a);
        l[nl++] = Line(p, v);
    }
}


/*--------------------------简单多边形--------------------------*/
double Area_Tri(Point p1, Point p2, Point p3){return 0.5 * fabs((p2 - p1) % (p3 - p1));}
double Area_Tri(double a, double b, double c){
    double p = (a+b+c)/2;
    return (double)sqrt((double)(p*(p-a)*(p-b)*(p-c)));
}
double Area_Poly(Point *p, int n){
    //求任意简单多边形的无向面积,前提要将p逆时针或顺时针排序

    if(n <= 2) return 0;
    Point o = Point(0, 0);
    p[n++] = p[0];
    double ans = 0;
    for(int i = 0; i < n-1; i++){
        ans += Area_Tri(o, p[i], p[i+1]) * sgn((p[i] - o) % (p[i+1] - o));
    }
    return fabs(ans);
}
void ConvexHull(Point *p, int n, Point *c, int &m){
    sort(p, p + n, cmpxy);
    m = 0;

    for(int i = 0; i < n; i++){
        while(m > 1 && sgn((c[m-1] - c[m-2]) % (p[i] - c[m-1])) <= 0) m--;
        c[m++] = p[i];
    }
    int k = m;
    for(int i = n - 2; i >= 0; i--){
        while(m > k && sgn((c[m-1] - c[m-2]) % (p[i] - c[m-1])) <= 0) m--;
        c[m++] = p[i];
    }
    if(m > 1) m--;
}
void Rotate_Convex_Hull(Point *c, int m){
    int id1 = 0, id2 = 0;
    for(int i = 0; i < m; i++) if(cmpYx(c[i], c[id1])) id1 = i;
    for(int i = 0; i < m; i++) if(cmpyX(c[i], c[id2])) id2 = i;
    int nexid1 = 0, nexid2 = 0;
    Vector v1 = Vector(-1, 0), v2 = Vector(1, 0), nexv1, nexv2;
    double rad1, rad2;
    int rm1 = id1, rm2 = id2;

    while(1){
        //solve here...

        //solve done

        nexid1 = id1 == m-1? 0 : id1+1;
        nexid2 = id2 == m-1? 0 : id2+1;
        nexv1 = c[nexid1] - c[id1];
        nexv2 = c[nexid2] - c[id2];
        rad1 = angle(v1, nexv1);
        rad2 = angle(v2, nexv2);

        if(sgn(rad1 - rad2) < 0){
            v1 = nexv1;
            id1 = nexid1;
            v2 = Rotate(v2, rad1);
        }
        else if(sgn(rad2 - rad1) < 0){
            v2 = nexv2;
            id2 = nexid2;
            v1 = Rotate(v1, rad2);
        }
        else{
            v1 = nexv1;
            id1 = nexid1;
            v2 = nexv2;
            id2 = nexid2;
        }

        if(id1 == rm1 && id2 == rm2) break;
    }
}


/*--------------------------读入--------------------------*/
Point readPoi(){
    int x, y;
    x = read(), y = read();
    //确保读入为int整形
    return Point(x, y);
}
Circle readCir(){
    Point p = readPoi();
    int r; r = read();
    //确保读入为int整形
    return Circle(p, r);
}
/*----------------------------------------------------*/

你可能感兴趣的:(My Geometry Template 2D(Updating...))