计算几何(圆相关模板) - 2D Geometry 110 in 1! - UVA 12304

计算几何(圆相关模板) - 2D Geometry 110 in 1! - UVA 12304

题意:

共 有 6 个 问 题 : 共有6个问题: 6

① 、 给 定 不 共 线 的 三 个 点 坐 标 , 输 出 外 接 圆 的 圆 心 和 半 径 。 ①、给定不共线的三个点坐标,输出外接圆的圆心和半径。 线

② 、 给 定 不 共 线 的 三 个 点 坐 标 , 输 出 内 切 圆 的 圆 心 和 半 径 。 ②、给定不共线的三个点坐标,输出内切圆的圆心和半径。 线
在这里插入图片描述

③ 、 给 定 圆 C 的 圆 心 坐 标 和 半 径 r , 输 出 过 定 点 P 的 圆 C 的 切 线 的 倾 角 。 ③、给定圆C的圆心坐标和半径r,输出过定点P的圆C的切线的倾角。 CrPC线
在这里插入图片描述

④ 、 给 定 一 个 定 点 P , 直 线 A B , 输 出 过 点 P 且 与 A B 相 切 的 圆 的 圆 心 坐 标 。 ④、给定一个定点P,直线AB,输出过点P且与AB相切的圆的圆心坐标。 P线ABPAB
在这里插入图片描述

⑤ 、 给 出 四 个 顶 点 A , B , C , D 的 坐 标 和 常 数 r , 直 线 A B 与 C D 相 交 , 计 算 A B 与 C D 的 半 径 为 r 公 切 圆 的 圆 心 。 ⑤、给出四个顶点A,B,C,D的坐标和常数r,直线AB与CD相交,计算AB与CD的半径为r公切圆的圆心。 A,B,C,Dr线ABCDABCDr
在这里插入图片描述

⑥ 、 给 定 两 个 不 相 交 的 圆 C 1 和 C 2 , 输 出 这 两 个 圆 公 切 圆 的 圆 心 。 ⑥、给定两个不相交的圆C_1和C_2,输出这两个圆公切圆的圆心。 C1C2

Sample Input

CircumscribedCircle 0 0 20 1 8 17
InscribedCircle 0 0 20 1 8 17
TangentLineThroughPoint 200 200 100 40 150
TangentLineThroughPoint 200 200 100 200 100
TangentLineThroughPoint 200 200 100 270 210
CircleThroughAPointAndTangentToALineWithRadius 100 200 75 190 185 65 100
CircleThroughAPointAndTangentToALineWithRadius 75 190 75 190 185 65 100
CircleThroughAPointAndTangentToALineWithRadius 100 300 100 100 200 100 100
CircleThroughAPointAndTangentToALineWithRadius 100 300 100 100 200 100 99
CircleTangentToTwoLinesWithRadius 50 80 320 190 85 190 125 40 30
CircleTangentToTwoDisjointCirclesWithRadius 120 200 50 210 150 30 25
CircleTangentToTwoDisjointCirclesWithRadius 100 100 80 300 250 70 50

Sample Output

(9.734940,5.801205,11.332389)
(9.113006,6.107686,5.644984)
[53.977231,160.730818]
[0.000000]
[]
[(112.047575,299.271627),(199.997744,199.328253)]
[(-0.071352,123.937211),(150.071352,256.062789)]
[(100.000000,200.000000)]
[]
[(72.231286,121.451368),(87.815122,63.011983),(128.242785,144.270867),(143.826621,85.831483)]
[(157.131525,134.836744),(194.943947,202.899105)]
[(204.000000,178.000000)]

分析:

圆 相 关 问 题 的 一 些 模 板 测 试 。 圆相关问题的一些模板测试。

思路参照:UVA - 12304 2D Geometry 110 in 1!

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>

using namespace std;

const double eps=1e-10;
const double pi=acos(-1.0);

struct Point 
{
    double x,y;
    Point(double x=0,double y=0) : x(x), y(y) {}
};

int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    else return x<0 ? -1 : 1;
}

typedef Point Vector;

Vector operator + (Vector A,Vector B) { return Vector(A.x+B.x,A.y+B.y); }

Vector operator - (Point A,Point B) { return Vector(A.x-B.x,A.y-B.y); }

Vector operator * (Vector A,double p) { return Vector(A.x*p,A.y*p); }

Vector operator / (Vector A,double p) { return Vector(A.x/p,A.y/p); }

bool operator < (const Point &a,const Point &b)
{
    return a.x<b.x || (!dcmp(a.x-b.x) && a.y<b.y);
}

bool operator == (const Point &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 angle(Vector v) { return atan2(v.y,v.x); }  

double angtox(Vector v)
{
    double ang=angle(v);
    if(dcmp(ang)<0) ang+=pi;
    if(dcmp(ang-pi)>=0) ang-=pi;
    return ang;
}

double dis2(Point A,Point B) { return (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y); }

double dis(Point A,Point B) { return sqrt(dis2(A,B)); }

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

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

struct Line
{
    Point v, p;
    Vector dir;
    double ang;
    
    Line() { }  
    Line(Point v, Point p):v(v), p(p){ dir=p-v; ang=atan2(dir.y,dir.x); }
    bool operator < (const Line& L) const 
    {  
        return ang < L.ang;  
    } 
    Point point(double t)
    {
        return v + dir*t;
    }
};

Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)   
{
    Vector u=P-Q;
    double t=Cross(w,u)/Cross(v,w);
    return P+v*t;
}

Point GetLineIntersection(Line L1, Line L2)    
{
    return GetLineIntersection(L1.v,L1.dir,L2.v,L2.dir);
}

double DistanceToLine(Point P,Point A,Point B) 
{
    Vector v1=B-A, v2=P-A;
    return fabs(Cross(v1,v2))/Length(v1);  
}

double DistanceToLine(Point P,Line L) 
{
    return DistanceToLine(P,L.v,L.p);
}

Point GetLineProjection(Point P,Point A,Point B)  
{
    Vector v=B-A;
    return A+v*(Dot(v,P-A)/Dot(v,v));
}

Point GetLineProjection(Point P,Line L)  
{
    return GetLineProjection(P,L.v,L.p);
}

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

Circle Excenter(Point a, Point b, Point c)
{
    double a1 = b.x - a.x;
    double b1 = b.y - a.y;
    double c1 = (a1*a1 + b1*b1)/2;
    double a2 = c.x - a.x;
    double b2 = c.y - a.y;
    double c2 = (a2*a2 + b2*b2)/2;
    double d = a1*b2 - a2*b1;
    Point O = Point(a.x + (c1*b2 - c2*b1)/d, a.y + (a1*c2 - a2*c1)/d);
    double r=dis(O,a);
    return Circle(O,r);
}

Circle getNqc(Point a, Point b, Point c) 
{
     double C = dis(a, b);
     double B = dis(a, c);
     double A = dis(b, c);
     Circle cir;
     cir.c.x = (A*a.x + B*b.x + C*c.x) / (A + B + C);
     cir.c.y = (A*a.y + B*b.y + C*c.y) / (A + B + C);
     cir.r = sqrt((A + B - C)*(A - B + C)*(-A + B + C) / (A + B + C)) / 2;
     return cir;
}

int getTangents(Point p,Circle C,Vector *v)
{
    Vector u=C.c-p;
    double dist=Length(u);
    if(dcmp(dist-C.r)<0) return 0;
    else if(dcmp(dist-C.r)==0)  //p在圆上
    {
        v[0]=Rotate(u,pi/2);
        return 1;
    }
    else
    {
        double ang=asin(C.r/dist);
        v[0]=Rotate(u,-ang);
        v[1]=Rotate(u,ang);
        return 2;
    }
}

int getLineCircleIntersection(Line a, Circle b, vector<Point>& res) 
{
    double h = DistanceToLine(b.c, a);
    if (dcmp(b.r-h) < 0) return 0;
    Point c = GetLineProjection(b.c, a);
    if (!dcmp(h-b.r)) 
    {
    	res.push_back(c);
    	return 1;
    }
    double w = sqrt(b.r * b.r - h * h);
    res.push_back(c + a.dir/Length(a.dir) * w); //直线L的单位向量
    res.push_back(c - a.dir/Length(a.dir) * w);
    sort(res.begin(), res.end());
    return 2;
}

vector<Point> Circle_Through_A_Point_And_Tangent_To_A_Line_With_Radius(Point a, Line b, double r) 
{
    vector<Point> res;
    Vector c = Normal(b.dir);
    Circle k(a, r);
    Point p=b.v+c*r, q=b.v-c*r;
    Line L1=Line(p, p+b.dir), L2=Line(q, q+b.dir);
    getLineCircleIntersection(L1, k, res);
    getLineCircleIntersection(L2, k, res);
    sort(res.begin(), res.end());
    return res;
}

vector<Point> Circle_Tangent_To_Two_Lines_With_Radius(Line L1,Line L2,double r)
{
    vector<Point> res;
    Vector n1 = Normal(L1.dir), n2 = Normal(L2.dir);
    
    Point p1=L1.v+n1*r, p2=L1.v-n1*r, q1=L2.v+n2*r, q2=L2.v-n2*r;
    Line L3(p1,p1+L1.dir), L4(p2,p2+L1.dir), L5(q1,q1+L2.dir), L6(q2,q2+L2.dir);
    Point O[5];
    O[1]=GetLineIntersection(L3,L5), O[2]=GetLineIntersection(L3,L6),
    O[3]=GetLineIntersection(L4,L5), O[4]=GetLineIntersection(L4,L6);
    for(int i=1;i<=4;i++) res.push_back(O[i]);
    sort(res.begin(),res.end());
    return res;
}

int getCircleCircleIntersection(Circle C1,Circle C2,vector<Point> &sol)
{
    double d=Length(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;
}

void print(vector<Point> &res)
{
    int num=res.size();
    printf("[");
    for(int i=0;i<num-1;i++) printf("(%lf,%lf),",res[i].x,res[i].y);
    if(num>0) printf("(%lf,%lf)",res[num-1].x,res[num-1].y);
    printf("]\n");
}

Point V[10];
char str[100];

int main()
{
    while(~scanf("%s",str))
    {
        if(strcmp(str,"CircumscribedCircle")==0)   
        {
            for(int i=0;i<3;i++) scanf("%lf%lf",&V[i].x,&V[i].y);
            Circle C=Excenter(V[0],V[1],V[2]);
            printf("(%lf,%lf,%lf)\n",C.c.x,C.c.y,C.r);
        }
        else if(strcmp(str,"InscribedCircle")==0)   
        {
            for(int i=0;i<3;i++) scanf("%lf%lf",&V[i].x,&V[i].y);
            Circle C=getNqc(V[0],V[1],V[2]);
            printf("(%lf,%lf,%lf)\n",C.c.x,C.c.y,C.r);
        }
        else if(strcmp(str,"TangentLineThroughPoint")==0) 
        {
            Circle C;
            Point P;
            scanf("%lf%lf%lf",&C.c.x,&C.c.y,&C.r);
            scanf("%lf%lf",&P.x,&P.y);
            Vector L[5];
            int num=getTangents(P,C,L);
            for(int i=0;i<num;i++) L[i]=angtox(L[i])/pi*180;
            sort(L,L+num);
            
            printf("[");
            for(int i=0;i<num-1;i++) printf("%lf,",L[i]);
            if(num>0) printf("%lf",L[num-1]);
            printf("]\n");
        }
        else if(strcmp(str,"CircleThroughAPointAndTangentToALineWithRadius")==0)
        {
            double r;
            for(int i=0;i<3;i++) scanf("%lf%lf",&V[i].x,&V[i].y);
            scanf("%lf",&r);
            vector<Point> res;
            res=Circle_Through_A_Point_And_Tangent_To_A_Line_With_Radius(V[0],Line(V[1],V[2]),r);
            sort(res.begin(),res.end());
            print(res);
        }
        else if(strcmp(str,"CircleTangentToTwoLinesWithRadius")==0)
        {
            for(int i=0;i<4;i++) scanf("%lf%lf",&V[i].x,&V[i].y);
            double r; scanf("%lf",&r);
            Line L1(V[0],V[1]), L2(V[2],V[3]);
            vector<Point> res;
            res=Circle_Tangent_To_Two_Lines_With_Radius(L1,L2,r);
            sort(res.begin(),res.end());
            print(res);
        }
        else if(strcmp(str,"CircleTangentToTwoDisjointCirclesWithRadius")==0)
        {
            double r1,r2,r;
            Point O1,O2;
            scanf("%lf%lf%lf",&O1.x,&O1.y,&r1);
            scanf("%lf%lf%lf",&O2.x,&O2.y,&r2);
            scanf("%lf",&r);
            Circle C1(O1,r1+r), C2(O2,r2+r);
            vector<Point> res;
            getCircleCircleIntersection(C1,C2,res);
            sort(res.begin(),res.end());
            print(res);
        }
    }
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值