UVA - 12304 2D Geometry 110 in 1!

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yzyyylx/article/details/82874077

题面

题意

计算几何模板题,一共有六种操作:
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();
	}
}

猜你喜欢

转载自blog.csdn.net/yzyyylx/article/details/82874077
110
今日推荐