题面
题意
计算几何模板题,一共有六种操作:
1.给出三个点,求它们的外接圆。
2.给出三个点,求它们的内切圆。
3.给出一个点个一个圆,求过这个点且与圆相切的直线与X轴的夹角。
4.给出一给点,一条线和r,求半径为r且与这条直线相切并过这个点的圆的圆心坐标。
5.给出两条直线和r,求半径为r且同时与这两条直线相切的圆的圆心坐标。
6.给出两个圆和r,求半径为r且同时与这两个圆相切的圆的圆心坐标。
如有多个答案,从小到大以此输出。
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<algorithm>
#define eps 1e-10
#define pi 3.14159265358979
#define db double
using namespace std;
char str[110];
struct Node
{
db x,y;
void in(){scanf("%lf%lf",&x,&y);}
bool operator < (const Node &u) const{if(fabs(x-u.x)>eps) return x<u.x;return y<u.y;}
Node operator + (const Node &u) const{Node res;res.x=x+u.x,res.y=y+u.y;return res;}
Node operator - (const Node &u) const{Node res;res.x=x-u.x,res.y=y-u.y;return res;}
db operator * (const Node &u) const{return x*u.x+y*u.y;}
Node operator * (const db &u) const{Node res;res.x=x*u,res.y=y*u;return res;}
Node operator / (const db &u) const{Node res;res.x=x/u,res.y=y/u;return res;}
};
struct Xn
{
Node num,v;
};
vector<Node>res;
inline db cj(Node u,Node v){return u.x*v.y-u.y*v.x;}//叉积
inline db lenf(Node u,Node v){return (u.x-v.x)*(u.x-v.x)+(u.y-v.y)*(u.y-v.y);}//两点间距离的平方
inline db len(Node u,Node v){return sqrt(lenf(u,v));}//两点间距离
inline Node make(db u,db v)
{
Node res;
res.x=u,res.y=v;
return res;
}
inline Node rot(Node u)//将一条直线旋转90度
{
Node res;
res.x=-u.y;
res.y=u.x;
return res;
}
inline Node jd(Xn u,Xn v)//求两直线的交点
{
Node res;
db t=(cj(u.num,u.v)-cj(v.num,u.v))/cj(v.v,u.v);
return v.v*t+v.num;
}
inline bool up(Node u,Xn v)//判断某个点是否在某条直线的上方
{
db t=u.y+(u.x-v.num.x)/v.v.x*v.v.y-v.num.y;
return t>eps;
}
inline bool on(Node u,Xn v)//判断某个点是否在某条直线上
{
db t=u.y+(u.x-v.num.x)*v.v.y/v.v.x-v.num.y;
return t>-eps&&t<eps;
}
namespace wjy//外接圆
{
Node a,b,c,ans;
Xn p,q;
void work()
{
a.in(),b.in(),c.in();
p.num=(a+c)/2,p.v=rot(c-a);
q.num=(a+b)/2,q.v=rot(b-a);
ans=jd(p,q);
printf("(%.6f,%.6f,%.6f)\n",ans.x,ans.y,len(ans,a));
}
}
namespace nqy//内切圆
{
Node a,b,c,ans;
Xn p,q;
db r;
inline Xn jpfx(Node w,Node u,Node v)
{
Xn p,q,res;
db t;
res.num=p.num=q.num=w;
p.v=u-w,q.v=v-w;
t=len(u,w)/len(v,w);
q.v=q.v*t;
res.v=p.v+q.v;
return res;
}
void work()
{
a.in(),b.in(),c.in();
p=jpfx(a,b,c),q=jpfx(b,a,c);
ans=jd(p,q);
r=fabs(cj(b-a,c-a))/(len(a,b)+len(b,c)+len(a,c));
printf("(%lf,%lf,%lf)\n",ans.x,ans.y,r);
}
}
namespace qxjj//求过某个点且与圆相切的直线与X轴的夹角。
{
Node a,b,c,res1,res2;
db r,t,r1,r2,l,ans1,ans2;
Xn p,q;
inline db zh(db u)
{
u=u/pi*180;
for(;u<0;u+=180);
for(;u>180;u-=180);
return u;
}
void work()
{
a.in();
scanf("%lf",&r1);
b.in();
l=len(a,b);
if(l*l<r1*r1-eps)
{
puts("[]");
return;
}
if(l*l<r1*r1+eps)
{
p.v=rot(b-a);
p.num=b;
printf("[%lf]\n",zh(atan(p.v.y/p.v.x)));
return;
}
r2=sqrt(l*l-r1*r1);
t=r2/r1;
c=(b-a)/(1+t*t)+a;
p.num=c,p.v=c-a;
p.v=rot(p.v);
t=l*t/(1+t*t);
res1=p.num+p.v*t/sqrt(p.v*p.v);
p.v=rot(rot(p.v));
res2=p.num+p.v*t/sqrt(p.v*p.v);
p.num=q.num=b;
p.v=b-res1,q.v=b-res2;
ans1=zh(atan(p.v.y/p.v.x)),ans2=zh(atan(q.v.y/q.v.x));
if(ans1>ans2) swap(ans1,ans2);
printf("[%lf,%lf]\n",ans1,ans2);
}
}
namespace gdxq//求过某个点并与某直线相切的圆
{
Node cen,a,b,c,res1,res2,o;
Xn p,q;
db r,t;
void work()
{
cen.in(),a.in(),b.in();
scanf("%lf",&r);
p.num=a,p.v=b-a;
if(on(cen,p))
{
p.num=cen;
p.v=rot(p.v);
t=r/sqrt(p.v*p.v);
res1=p.num+p.v*t;
res2=p.num-p.v*t;
if(res2<res1) swap(res1,res2);
printf("[(%lf,%lf),(%lf,%lf)]\n",res1.x,res1.y,res2.x,res2.y);
return;
}
q.v=rot(p.v);
q.num=cen;
o=jd(p,q);
q.num=o;
q.v=cen-o;
t=r/sqrt(q.v*q.v);
c=q.num+q.v*t;
if(r*r+eps<lenf(cen,c))
{
puts("[]");
return;
}
t=sqrt(r*r-lenf(cen,c))/sqrt(p.v*p.v);
if(t<eps)
{
printf("[(%lf,%lf)]\n",c.x,c.y);
return;
}
res1=c+p.v*t;
res2=c-p.v*t;
if(res2<res1) swap(res1,res2);
printf("[(%lf,%lf),(%lf,%lf)]\n",res1.x,res1.y,res2.x,res2.y);
}
}
namespace ylxq//求与两直线相切的圆
{
Node a,b,c,d;
Xn o,p,q,p1,p2,q1,q2;
db t,r;
void work()
{
int i,j;
a.in(),b.in();
p.num=a,p.v=b-a;
a.in(),b.in();
scanf("%lf",&r);
q.num=a,q.v=b-a;
o=p,o.v=rot(p.v);
t=r/sqrt(o.v*o.v);
o.v=o.v*t;
p1.num=p.num+o.v,p1.v=p.v;
p2.num=p.num-o.v,p2.v=p.v;
o=q,o.v=rot(q.v);
t=r/sqrt(o.v*o.v);
o.v=o.v*t;
q1.num=q.num+o.v,q1.v=q.v;
q2.num=q.num-o.v,q2.v=q.v;
res.clear();
res.push_back(jd(p1,q1));
res.push_back(jd(p1,q2));
res.push_back(jd(p2,q1));
res.push_back(jd(p2,q2));
sort(res.begin(),res.end());
printf("[");
for(i=0;i<res.size();i++)
{
if(i) printf(",");
printf("(%lf,%lf)",res[i].x,res[i].y);
}
printf("]\n");
}
}
namespace ylyq//求与两圆相切的圆
{
Node o1,o2,a,b;
Xn p,q;
db r1,r2,r,d,t,l,ca;
void work()
{
o1.in(),scanf("%lf",&r1);
o2.in(),scanf("%lf",&r2);
scanf("%lf",&r);
r1+=r,r2+=r;
l=len(o1,o2);
if(r1+r2+eps<l || fabs(r1-r2)>l+eps)
{
puts("[]");
return;
}
ca=(lenf(o1,o2)+r1*r1-r2*r2)/(2*l*r1);
d=t=r1*ca;
p.num=o1;
p.v=o2-o1;
t=t/sqrt(p.v*p.v);
q.num=p.num+p.v*t;
q.v=rot(p.v);
t=sqrt(r1*r1-d*d);
t=t/sqrt(q.v*q.v);
q.v=q.v*t;
a=q.num+q.v;
b=q.num-q.v;
if(b<a) swap(a,b);
printf("[(%lf,%lf)",a.x,a.y);
if(lenf(a,b)>eps) printf(",(%lf,%lf)",b.x,b.y);
printf("]\n");
}
}
int main()
{
int i,j;
while(~scanf("%s",str))
{
if(strlen(str)==19) wjy::work();
else if(strlen(str)==15) nqy::work();
else if(strlen(str)==23) qxjj::work();
else if(strlen(str)==46) gdxq::work();
else if(strlen(str)==33) ylxq::work();
else ylyq::work();
}
}