2D Geometry 110 in 1! UVA - 12304

!!!:注意Line的初始化

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
#define bug(x) printf("sum:%lld\n",x)

const int mod=1e9+7;
const double eps=1e-8,pi=acos(-1),inf=1.0/0.0;

class Point;
typedef Point Vec;
//三态函数比较;精度问题
int dcmp(double x){
    return x>-eps?(x>eps?1:0):-1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    //向量与常数 注意常数要放在后面
    Vec operator*(double p) {return Vec(x*p,y*p);}
    Vec operator/(double p) {return Vec(x/p,y/p);}
    Vec operator-(Vec obj)  {return Vec(x-obj.x,y-obj.y);}
    Vec operator+(Vec obj)  {return Vec(x+obj.x,y+obj.y);}
    //点积
    double operator*(Vec obj) {return x*obj.x+y*obj.y;}
    //叉积
    double operator^(Vec obj) {return x*obj.y-y*obj.x;}
    //两个向量的夹角 A*B=|A|*|B|*cos(th)
    double Angle(Vec B)  {return acos((*this)*B/(*this).len()/B.len());}
    //两条向量平行四边形的面积
    double Area(Vec B)   {return fabs((*this)^B);}
    //向量旋转
    //旋转公式
    //  Nx     (cos  -sin) x
    //  Ny     (sin   cos) y
    Vec Rotate(double rad)  {return Vec(x*cos(rad)-y*sin(rad),x*sin(rad)+y*cos(rad));}
    //返回向量的法向量,即旋转pi/2
    Vec Normal()  {return Vec(-y,x);}
    //返回向量的长度,或者点距离原点的距离
    double len()  {return hypot(x,y);}
    double len2() {return x*x+y*y;}
    //返回两点之间的距离
    double dis(Point obj)   {return hypot(x-obj.x,y-obj.y);} //hypot 给定直角三角形的两条直角边,返回斜边边长
     //向量的极角 atan2(y,x)

     double th(){return atan2(y,x);}
     //double ans=atan2(y,x)+pi*2; if(dcmp(ans-2.0*pi)>0)ans-=2.0*pi; return ans;
     bool operator==(Point obj) {return dcmp(x-obj.x)==0&&dcmp(y-obj.y)==0;}
     bool operator<(Point obj)  {return x<obj.x||(x==obj.x&&y<obj.y);}
};


//!!! 特别注意Line的初始化 (p,q-p) 第一个是点,第二个是向量
struct Line{
    Point u;Vec v;//起点,方向向量
    Line(Point p,Vec _v){
        u=p,v=unit(_v);//单位化方向向量
    }
    Vec unit(Vec v){ //向量单位化
        double t=v.len();
        if(dcmp(t)==0)return v;
        return v/t;
    }
    Point get_point(double t){
        return u+v*t;
    }
};

Point vec[10];

//点在直线上的投影
Point foot_point(Point P,Line L){
    Point v=L.v;
    return L.u+v*(v*(P-L.u));
}

//垂直平分线
Line Perpen_bi(Point a,Point b){
    return Line((a+b)/2,(b-a).Normal());
}
//点到直线的距离
double Point_Dis_Line(Point p,Line L){
    Vec v1=L.v,v2=p-L.u;return fabs(v1^v2/v1.len());
}
//点到线段距离
double DistanceToSegment(Point P,Point A,Point B)
{
    if(A==B) return (P-A).len();
    Point v1=B-A,v2=P-A,v3=P-B;
    if(dcmp(v1*v2)<0) return v2.len();
    else if(dcmp(v1*v3)>0) return v3.len();
    else return fabs(v1^v2/v1.len());
}
//直线与直线的交点
void Line_Line_Jiao(Line L1,Line L2,int& cnt){
    Point P=L1.u,v=L1.v;
    Point Q=L2.u,w=L2.v;
    if(dcmp(v^w)==0)return;//平行,不存在交点
    Vec u=P-Q;
    double t=w^u/(v^w);
    //return P+v*t;

    vec[cnt++]=P+v*t;
}

/// 过两点p1, p2的直线一般方程ax+by+c=0  (x2-x1)(y-y1) = (y2-y1)(x-x1)
void getLineGeneralEquation(const Point& p1, const Point& p2, double& a, double&b, double &c)
{
    a = p2.y-p1.y;
    b = p1.x-p2.x;
    c = -a*p1.x - b*p1.y;
}


struct Circle{
    Point c; double r;
    Circle(Point c,double r):c(c),r(r){}
    Point getpoint(double a){return Point(c.x+cos(a)*r,c.y+sin(a)*r);}
};
//求三点的外接圆
Circle get_wai_cir(Point p1,Point p2,Point p3){
    double Bx=p2.x-p1.x,By=p2.y-p1.y;
    double Cx=p3.x-p1.x,Cy=p3.y-p1.y;
    double D=2*(Bx*Cy-By*Cx);
    double cx=(Cy*(Bx*Bx+By*By)-By*(Cx*Cx+Cy*Cy))/D+p1.x;
    double cy=(Bx*(Cx*Cx+Cy*Cy)-Cx*(Bx*Bx+By*By))/D+p1.y;
    Point p=Point(cx,cy);
    return Circle(p,(p1-p).len());
}
//求三点的内接圆
Circle get_nei_cir(Point p1,Point p2,Point p3){
    double a=(p2-p3).len();
    double b=(p3-p1).len();
    double c=(p1-p2).len();
    Point p=(p1*a+p2*b+p3*c)/(a+b+c);
    return Circle(p,Point_Dis_Line(p,Line(p1,p2-p1)));
}

//直线与圆的交点
void Line_Cir_Jiao(Line L,Circle C,int& cnt){
    Point f=foot_point(C.c,L);
    double d=(C.c-f).len();
    if(dcmp(d-C.r)>0)return;
    if(dcmp(d-C.r)==0){vec[cnt++]=f;return;}
    double t=sqrt(C.r*C.r-d*d);
    vec[cnt++]=f+L.v*t;
    vec[cnt++]=f-L.v*t;
}

//两圆的交点
void Cir_Cir_Jiao(Circle C1,Circle C2,Point* vec,int& cnt){
    double d=(C1.c-C2.c).len();

    if(dcmp(d)==0){
        if(dcmp(C1.r-C2.r)==0)cnt=-1;//完全重合
        return ;//包含关系
    }

    if(dcmp(C1.r+C2.r-d)<0)return; //想离
    if(dcmp(fabs(C1.r-C2.r)-d)>0)return; //包含

    double a=(C2.c-C1.c).th();
    double cosa=(C1.r*C1.r+d*d-C2.r*C2.r)/(2.0*C1.r*d);

    Line L=Line(C1.c,C2.c-C1.c);
    Point h=L.u+L.v*C1.r*cosa;
    Line t=Line(h,L.v.Normal());
    Line_Cir_Jiao(t,C1,cnt);
}

//过定点做圆的切线
void Point_Cir_Qie(Point p,Circle C,Vec* v,int& cnt){
    Vec u=C.c-p;
    double dis=u.len();
    if(dcmp(dis-C.r)<0) return;
    if(dcmp(dis-C.r)==0){
        Vec t=u.Normal();
        v[cnt++]=t;
        return;
    }
    double r=sqrt(dis*dis-C.r*C.r);
    double th=asin(C.r/dis);
    vec[cnt++]=u.Rotate(-th);
    vec[cnt++]=u.Rotate(th);
}


Point p[10],p1[10],p2[10];
char str[100];

double ans_angle[10];
int main(){
   // freopen("123.txt","w",stdout);
    while(scanf(" %s",str)==1){
        if(!strcmp(str,"CircumscribedCircle")){
            double x1,y1,x2,y2,x3,y3;
            scanf("%lf %lf %lf %lf %lf %lf",&x1,&y1,&x2,&y2,&x3,&y3);
            Point A=Point(x1,y1),B=Point(x2,y2),C=Point(x3,y3);
            Circle ans=get_wai_cir(A,B,C);
            printf("(%.6f,%.6f,%.6f)\n",ans.c.x,ans.c.y,ans.r);
        }
        else if(!strcmp(str,"InscribedCircle")){
            double x1,y1,x2,y2,x3,y3;
            scanf("%lf %lf %lf %lf %lf %lf",&x1,&y1,&x2,&y2,&x3,&y3);
            Point A=Point(x1,y1),B=Point(x2,y2),C=Point(x3,y3);
            Circle ans=get_nei_cir(A,B,C);
            printf("(%.6f,%.6f,%.6f)\n",ans.c.x,ans.c.y,ans.r);
        }
        else if(!strcmp(str,"TangentLineThroughPoint")){
            double xc,yc,r,xp,yp;
            scanf("%lf %lf %lf %lf %lf",&xc,&yc,&r,&xp,&yp);
            Circle c0=Circle(Point(xc,yc),r);
            Point p=Point(xp,yp);
            int cnt=0;
            Point_Cir_Qie(p,c0,vec,cnt);

            rep(i,0,cnt){
                ans_angle[i]=vec[i].th()/pi*180;
                if(dcmp(ans_angle[i])<0)ans_angle[i]+=180;
                if(dcmp(ans_angle[i]-180)==0)ans_angle[i]=0;
            }
            if(cnt>0)sort(ans_angle,ans_angle+cnt);

            printf("[");
            rep(i,0,cnt-1) printf("%.6f,",ans_angle[i]);
            if(cnt>0)printf("%.6f",ans_angle[cnt-1]);
            printf("]\n");
        }
        else if(!strcmp(str,"CircleThroughAPointAndTangentToALineWithRadius")){
            double xp,yp,x1,y1,x2,y2,r;
            scanf("%lf %lf %lf %lf %lf %lf %lf",&xp,&yp,&x1,&y1,&x2,&y2,&r);
            Point p=Point(xp,yp);

            Circle C=Circle(p,r);
            Point p1=Point(x1,y1),p2=Point(x2,y2);
            Line L=Line(p1,p2-p1);

            //和直线L 平行相距为r的直线
            Line L1=Line(p1+L.v.Normal()*r,p2-p1);
            Line L2=Line(p1-L.v.Normal()*r,p2-p1);

            int cnt=0;
            Line_Cir_Jiao(L1,C,cnt);
            Line_Cir_Jiao(L2,C,cnt);

            if(cnt>0)sort(vec,vec+cnt);
            printf("[");
            rep(i,0,cnt-1)printf("(%.6f,%.6f),",vec[i].x,vec[i].y);
            if(cnt)printf("(%.6f,%.6f)",vec[cnt-1].x,vec[cnt-1].y);
            printf("]\n");

        }
        else if(!strcmp(str,"CircleTangentToTwoLinesWithRadius")){
             double x,y;
             rep(i,0,4){
                scanf("%lf %lf",&x,&y);
                p[i]=Point(x,y);
             }
             double r;scanf("%lf",&r);

             //平行的相距 为r的直线
             Line L=Line(p[0],p[1]-p[0]),R=Line(p[2],p[3]-p[2]);
             Line L1=Line(L.u+L.v.Normal()*r,L.v),L2=Line(L.u-L.v.Normal()*r,L.v);
             Line L3=Line(R.u+R.v.Normal()*r,R.v),L4=Line(R.u-R.v.Normal()*r,R.v);

             int cnt=0;
             Line_Line_Jiao(L1,L3,cnt);
             Line_Line_Jiao(L1,L4,cnt);
             Line_Line_Jiao(L2,L3,cnt);
             Line_Line_Jiao(L2,L4,cnt);

            if(cnt>0)sort(vec,vec+cnt);
            printf("[");
            rep(i,0,cnt-1)printf("(%.6f,%.6f),",vec[i].x,vec[i].y);
            if(cnt)printf("(%.6f,%.6f)",vec[cnt-1].x,vec[cnt-1].y);
            printf("]\n");
        }
        else{
            double x1,y1,r1,x2,y2,r2,r;
            scanf("%lf %lf %lf %lf %lf %lf %lf",&x1,&y1,&r1,&x2,&y2,&r2,&r);
            Circle c1=Circle(Point(x1,y1),r1+r),c2=Circle(Point(x2,y2),r2+r);
            int cnt=0;
            Cir_Cir_Jiao(c1,c2,vec,cnt);

            if(cnt>0)sort(vec,vec+cnt);
            printf("[");
            rep(i,0,cnt-1) printf("(%.6f,%.6f),",vec[i].x,vec[i].y);
            if(cnt>0)printf("(%.6f,%.6f)",vec[cnt-1].x,vec[cnt-1].y);
            printf("]\n");
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值