计算几何初步(刷蓝书)

 

头文件

/*author:revolIA*/
/*
492
357
816
*/
#include
#define max(a,b) (a>b?a:b)
#define min(a,b) (ausing namespace std;
typedef long long ll;
const int maxn = 1e3+7;
const double esp = 1e-6,pi = acos(-1);
double o2(double x){return x*x;}
//
int dcmp(double x){
    if(fabs(x)return 0;
    return x<0?-1:1;
}
struct Point{
    double x,y;
    void read(){scanf("%lf%lf",&x,&y);}
    Point(double x = 0,double y = 0):x(x),y(y){}
};
double Cross(const Point A,const Point B){ return A.x*B.y-A.y*B.x; }
double Dot(const Point A,const Point B){ return A.x*B.x+A.y*B.y; }
double Len(const Point A){ return sqrt(Dot(A,A)); }
double Angle(const Point A,const Point B){ return acos(Dot(A,B)/Len(A)/Len(B)); }
Point operator + (const Point A,const Point B){ return Point(A.x+B.x,A.y+B.y); }
Point operator - (const Point A,const Point B){ return Point(A.x-B.x,A.y-B.y); }
Point operator * (const Point A,const double B){ return Point(A.x*B,A.y*B); }
Point operator / (const Point A,const double B){ return Point(A.x/B,A.y/B); }
Point Rotate(const Point A,double rad){return Point(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));}
//负数表示顺时针
Point Normal(const Point A){return Point(-A.y/Len(A),A.x/Len(A));}//法向量
bool operator == (const Point A,const Point B){return !dcmp(A.x-B.x)&&!dcmp(A.y-B.y); }
bool operator != (const Point A,const Point B){return !(A == B);}
bool operator < (const Point A,const Point B){return dcmp(A.x-B.x)<0 || (!dcmp(A.x-B.x)&&dcmp(A.y-B.y)<0);}
typedef Point Vector;
bool quickRepel(Point x1,Point y1,Point x2,Point y2){//快速排斥
    Point Lx = Point(min(x1.x,y1.x),min(x1.y,y1.y));
    Point Rx = Point(max(x1.x,y1.x),max(x1.y,y1.y));

    Point Ly = Point(min(x2.x,y2.x),min(x2.y,y2.y));
    Point Ry = Point(max(x2.x,y2.x),max(x2.y,y2.y));

    Point L = Point(max(Lx.x,Ly.x),max(Lx.y,Ly.y));
    Point R = Point(min(Rx.x,Ry.x),min(Rx.y,Ry.y));

    return (L.x<=R.x) && (L.y<=R.y);
}
bool OnSegment(Point P,Point x,Point y){//点在线段上
    if(P == x||P == y)return 1;
    return !dcmp(Cross(x-P,y-P))&&dcmp(Dot(P-x,P-y))<0;
}
bool straddle(Point x1,Point y1,Point x2,Point y2){//跨立实验(线段是否有交点)
    if(!quickRepel(x1,y1,x2,y2))return 0;
    double c1 = Cross(y1-x1,x2-x1),c2 = Cross(y1-x1,y2-x1);
    double c3 = Cross(y2-x2,x1-x2),c4 = Cross(y2-x2,y1-x2);
    return dcmp(c1)*dcmp(c2)<=0 && dcmp(c3)*dcmp(c4)<=0;
    //允许部分重合或在端点重合
    //return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
    //必须只有一个交点且不在端点上
}
Point LinearIntersection(Point P,Vector v,Point Q,Vector w){//解直线交点
    assert(v != w);//Parallel 平行线
    Vector u = P-Q;
    double t = Cross(w,u)/Cross(v,w);
    return P+v*t;
}
Point GetLineProjection(Point P,Point A,Point B){//P投影到AB上的点
    Vector v = B-A;
    return A+v*(Dot(v,P-A)/Dot(v,v));
}
Point SymmetricPoint(Point P,Point A,Point B){//P关于AB的对称点
    return GetLineProjection(P,A,B)*2.0-P;
}
double DistanceToline(Point P,Point A,Point B){//点到直线距离
    Vector v1 = B-A,v2 = P-A;
    return fabs(Cross(v1,v2))/Len(v1);
}
double DistanceToSegment(Point P,Point A,Point B){//点到线段距离
    if(A == B)return Len(P-A);
    Vector v1 = B-A,v2 = P-A,v3 = P-B;
    if(dcmp(Dot(v1,v2))<0)return Len(v2);
    if(dcmp(Dot(v1,v3))>0)return Len(v3);
    return fabs(Cross(v1,v2))/Len(v1);
}
//直线
struct Line{
    Point p;
    Vector v;
    double ang;
    Line(){}
    Line(Point p,Vector v):p(p),v(v){ang = atan2(v.y,v.x);}
    Point point(double t){
        return p+v*t;
    }
    bool operator < (const Line& T)const{
        return ang<T.ang;
    }
};
//
struct Circle{
    Point c;
    double r;
    Circle(){}
    Circle(Point c,double r):c(c),r(r){}
    void read(){
        c.read();
        scanf("%lf",&r);
    }
    Point point(double a){return Point(c.x+cos(a)*r,c.y+sin(a)*r);}
};
//圆和直线交点
int getLineCircleIntersection(Line L,Circle C,double& t1,double& t2,vector& 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;
}
//向量极角
double Angle(Vector v){return atan2(v.y,v.x);}
//圆和圆的交点
int getCircleCircleIntersection(Circle C1,Circle C2,vector& sol){
    double d =  Len(C1.c-C2.c);
    if(dcmp(d) == 0){
        if(dcmp(C1.r-C2.r) == 0)return -1;//重合
        return 0;
    }
    if(dcmp(C1.r+C2.r-d)<0)return 0;
    if(dcmp(fabs(C1.r-C2.r)-d)>0)return 0;
    double a = Angle(C2.c-C1.c);
    double da = acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));
    Point p1 = C1.point(a-da),p2 = C1.point(a+da);
    sol.push_back(p1);
    if(p1 == p2)return 1;
    sol.push_back(p2);
    return 2;
}
//过定点求圆切线
int getTangents(Point p,Circle C,Vector* v){
    Vector u = C.c-p;
    double dist = Len(u);
    if(dcmp(dist - C.r)<0)return 0;
    if(dcmp(dist-C.r) == 0){
        v[0] = Rotate(u,pi/2);
        return 1;
    }
    double ang = asin(C.r/dist);
    v[0] = Rotate(u,-ang);
    v[1] = Rotate(u,+ang);
    return 2;
}
//圆和圆之间公切线
int getTangents(Circle A,Circle B,Point *a,Point *b){
    int cnt = 0;
    if(A.r<B.r){
        swap(A,B);
        swap(a,b);
    }
    double d = Len(A.c-B.c);
    double rdiff = A.r-B.r;
    double rsum = A.r+B.r;
    if(dcmp(d - rdiff)<0)return 0;//内含
    double base = atan2(B.c.y-A.c.y,B.c.x-A.c.x);
    if(!dcmp(d) && !dcmp(A.r-B.r))return -1;//无限的切线
    if(!dcmp(d-rdiff)){//内切
        a[cnt] = A.point(base);
        b[cnt] = B.point(base);
        cnt++;
        return 1;
    }
    double ang = acos((A.r-B.r)/d);
    a[cnt] = A.point(base+ang);
    b[cnt] = B.point(base+ang);
    cnt++;
    a[cnt] = A.point(base-ang);
    b[cnt] = B.point(base-ang);
    cnt++;
    if(!dcmp(d-rsum)){
        a[cnt] = A.point(base);
        b[cnt] = B.point(pi+base);
        cnt++;
    }else if(dcmp(d - rsum)>0){
        double ang = acos((A.r+B.r)/d);
        a[cnt] = A.point(base+ang);
        b[cnt] = B.point(pi+base+ang);
        cnt++;
        a[cnt] = A.point(base-ang);
        b[cnt] = B.point(pi+base-ang);
        cnt++;
    }
    return cnt;
}
//计算圆心角lat表示纬度,-90<=w<=90,lng表示经度
//返回两点所在大圆劣弧对应圆心角,0<=angle<=pi
double angle(double lng1,double lat1,double lng2,double lat2){
    double dlng=fabs(lng1-lng2)*pi/180;
    while (dlng>=pi+pi)
        dlng-=pi+pi;
    if (dlng>pi)
        dlng=pi+pi-dlng;
    lat1*=pi/180,lat2*=pi/180;
    return acos(cos(lat1)*cos(lat2)*cos(dlng)+sin(lat1)*sin(lat2));
}
//计算距离,r为球半径
double line_dist(double r,double lng1,double lat1,double lng2,double lat2){
    double dlng=fabs(lng1-lng2)*pi/180;
    while (dlng>=pi+pi)
        dlng-=pi+pi;
    if (dlng>pi)
        dlng=pi+pi-dlng;
    lat1*=pi/180,lat2*=pi/180;
    return r*sqrt(2-2*(cos(lat1)*cos(lat2)*cos(dlng)+sin(lat1)*sin(lat2)));
}
//计算球面距离,r为球半径
inline double sphere_dist(double r,double lng1,double lat1,double lng2,double lat2){
    return r*angle(lng1,lat1,lng2,lat2);
}
int isPointInPolygon(Point p,vector poly){
    int wn = 0;
    int n = poly.size();
    for(int i=0;i){
        if(OnSegment(p,poly[i],poly[(i+1)%n])){
            return -1;//in the edge
        }
        int k = dcmp(Cross(poly[(i+1)%n]-poly[i],p-poly[i]));
        int d1 = dcmp(poly[i].y-p.y);
        int d2 = dcmp(poly[(i+1)%n].y-p.y);
        if(k>0 && d1<=0 && d2>0)wn++;
        if(k<0 && d2<=0 && d1>0)wn--;
    }
    if(wn)return 1;//inside
    return 0;//outside
}
int ConvexHull(Point* p,int n,Point* ch){
    sort(p,p+n);
    int m = 0;
    for(int i=0;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];
    }
    if(n>1)m--;
    return m;
}
double PolygonArea(Point* A,int n){
    double ans = 0;
    for(int i=0;i)
        ans += Cross(A[i],A[(i+1)%n]);
    return ans/2;
}

 

 

 tangents

求圆的公切线

注意各种dcmp代替直接判断double的大小吧 

struct Node{
    Point a,b;
    double dist;
    bool operator < (const Node T)const{
        return a<T.a;
    }
}T[20];
Point a[20],b[20];
int main(){
    while(true){
        Circle A,B;
        A.read(),B.read();
        if(!dcmp(A.c.x)&&!dcmp(A.c.y)&&!dcmp(A.r)&&!dcmp(B.c.x)&&!dcmp(B.c.y)&&!dcmp(B.r))break;
        int ans = getTangents(A,B,a,b);
        if(~ans){
            printf("%d\n",ans);
            if(!ans)continue;
            for(int i=0;i){
                T[i].a = a[i];
                T[i].b = b[i];
                T[i].dist = Len(a[i]-b[i]);
            }
            sort(T,T+ans);
            for(int i=0;i){
                printf("%.5f %.5f %.5f %.5f %.5f\n",T[i].a.x,T[i].a.y,T[i].b.x,T[i].b.y,T[i].dist);
            }
        }else{
            printf("-1\n");
        }
    }
    return 0;
}

Board Wrapping 

凸包板子

int main(){
    int T;
    Point P[2500],ch[2500];
    scanf("%d",&T);
    while(T--){
        int n,pc = 0;
        double are1 = 0;
        scanf("%d",&n);
        for(int i=0;i){
            double x,y,w,h,j,ang;
            scanf("%lf%lf%lf%lf%lf",&x,&y,&w,&h,&j);
            Point o(x,y);
            ang = -(j*pi/180);
            P[pc++] = o+Rotate(Vector(-w/2,-h/2),ang);
            P[pc++] = o+Rotate(Vector(w/2,-h/2),ang);
            P[pc++] = o+Rotate(Vector(-w/2,h/2),ang);
            P[pc++] = o+Rotate(Vector(w/2,h/2),ang);
            are1 += w*h;
        }
        int m = ConvexHull(P,pc,ch);
        //printf("%d\n",m);
        double are2 = PolygonArea(ch,m);
        printf("%.1f %%\n",are1*100/are2);
    }
    return 0;
}

 

 

 

 

/*author:revolIA*//*492357816*/#include#define max(a,b) (a>b?a:b)#define min(a,b) (a    Point Ly = Point(min(x2.x,y2.x),min(x2.y,y2.y));    Point Ry = Point(max(x2.x,y2.x),max(x2.y,y2.y));
    Point L = Point(max(Lx.x,Ly.x),max(Lx.y,Ly.y));    Point R = Point(min(Rx.x,Ry.x),min(Rx.y,Ry.y));
    return (L.x<=R.x) && (L.y<=R.y);}bool OnSegment(Point P,Point x,Point y){//点在线段上    if(P == x||P == y)return 1;    return !dcmp(Cross(x-P,y-P))&&dcmp(Dot(P-x,P-y))<0;}bool straddle(Point x1,Point y1,Point x2,Point y2){//跨立实验(线段是否有交点)    if(!quickRepel(x1,y1,x2,y2))return 0;    double c1 = Cross(y1-x1,x2-x1),c2 = Cross(y1-x1,y2-x1);    double c3 = Cross(y2-x2,x1-x2),c4 = Cross(y2-x2,y1-x2);    return dcmp(c1)*dcmp(c2)<=0 && dcmp(c3)*dcmp(c4)<=0;    //允许部分重合或在端点重合    //return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;    //必须只有一个交点且不在端点上}Point LinearIntersection(Point P,Vector v,Point Q,Vector w){//解直线交点    assert(v != w);//Parallel 平行线    Vector u = P-Q;    double t = Cross(w,u)/Cross(v,w);    return P+v*t;}Point GetLineProjection(Point P,Point A,Point B){//P投影到AB上的点    Vector v = B-A;    return A+v*(Dot(v,P-A)/Dot(v,v));}Point SymmetricPoint(Point P,Point A,Point B){//P关于AB的对称点    return GetLineProjection(P,A,B)*2.0-P;}double DistanceToline(Point P,Point A,Point B){//点到直线距离    Vector v1 = B-A,v2 = P-A;    return fabs(Cross(v1,v2))/Len(v1);}double DistanceToSegment(Point P,Point A,Point B){//点到线段距离    if(A == B)return Len(P-A);    Vector v1 = B-A,v2 = P-A,v3 = P-B;    if(dcmp(Dot(v1,v2))<0)return Len(v2);    if(dcmp(Dot(v1,v3))>0)return Len(v3);    return fabs(Cross(v1,v2))/Len(v1);}//直线struct Line{    Point p;    Vector v;    double ang;    Line(){}    Line(Point p,Vector v):p(p),v(v){ang = atan2(v.y,v.x);}    Point point(double t){        return p+v*t;    }    bool operator < (const Line& T)const{        return ang& 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;}//向量极角double Angle(Vector v){return atan2(v.y,v.x);}//圆和圆的交点int getCircleCircleIntersection(Circle C1,Circle C2,vector& sol){    double d =  Len(C1.c-C2.c);    if(dcmp(d) == 0){        if(dcmp(C1.r-C2.r) == 0)return -1;//重合        return 0;    }    if(dcmp(C1.r+C2.r-d)<0)return 0;    if(dcmp(fabs(C1.r-C2.r)-d)>0)return 0;    double a = Angle(C2.c-C1.c);    double da = acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));    Point p1 = C1.point(a-da),p2 = C1.point(a+da);    sol.push_back(p1);    if(p1 == p2)return 1;    sol.push_back(p2);    return 2;}//过定点求圆切线int getTangents(Point p,Circle C,Vector* v){    Vector u = C.c-p;    double dist = Len(u);    if(dcmp(dist - C.r)<0)return 0;    if(dcmp(dist-C.r) == 0){        v[0] = Rotate(u,pi/2);        return 1;    }    double ang = asin(C.r/dist);    v[0] = Rotate(u,-ang);    v[1] = Rotate(u,+ang);    return 2;}//圆和圆之间公切线int getTangents(Circle A,Circle B,Point *a,Point *b){    int cnt = 0;    if(A.r0){        double ang = acos((A.r+B.r)/d);        a[cnt] = A.point(base+ang);        b[cnt] = B.point(pi+base+ang);        cnt++;        a[cnt] = A.point(base-ang);        b[cnt] = B.point(pi+base-ang);        cnt++;    }    return cnt;}//计算圆心角lat表示纬度,-90<=w<=90,lng表示经度//返回两点所在大圆劣弧对应圆心角,0<=angle<=pidouble angle(double lng1,double lat1,double lng2,double lat2){double dlng=fabs(lng1-lng2)*pi/180;while (dlng>=pi+pi)dlng-=pi+pi;if (dlng>pi)dlng=pi+pi-dlng;lat1*=pi/180,lat2*=pi/180;return acos(cos(lat1)*cos(lat2)*cos(dlng)+sin(lat1)*sin(lat2));}//计算距离,r为球半径double line_dist(double r,double lng1,double lat1,double lng2,double lat2){double dlng=fabs(lng1-lng2)*pi/180;while (dlng>=pi+pi)dlng-=pi+pi;if (dlng>pi)dlng=pi+pi-dlng;lat1*=pi/180,lat2*=pi/180;return r*sqrt(2-2*(cos(lat1)*cos(lat2)*cos(dlng)+sin(lat1)*sin(lat2)));}//计算球面距离,r为球半径inline double sphere_dist(double r,double lng1,double lat1,double lng2,double lat2){return r*angle(lng1,lat1,lng2,lat2);}int isPointInPolygon(Point p,vector poly){    int wn = 0;    int n = poly.size();    for(int i=0;i0 && d1<=0 && d2>0)wn++;        if(k<0 && d2<=0 && d1>0)wn--;    }    if(wn)return 1;//inside    return 0;//outside}int ConvexHull(Point* p,int n,Point* ch){    sort(p,p+n);    int m = 0;    for(int i=0;i1 && 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];    }    if(n>1)m--;    return m;}double PolygonArea(Point* A,int n){    double ans = 0;    for(int i=0;i

你可能感兴趣的:(计算几何初步(刷蓝书))