UVAOJ 12304 - 2D Geometry 110 in 1!

这是一道几何模板题,但是难度就在于把六种几何问题放在了一起,代码一长就不好改错。另外在训练指南上面的翻译只是把大致意思翻译了,有些细节没有翻译出来。比如说答案里面数值的排序要按照从小到大的顺序,点的顺序也要进行排序。

第一个问题没有按照训练指南上面的方法做,我用垂直平分线的交点来做的。

代码如下:

#include<iostream>
#include<cmath>
#include<stdlib.h>
#include<iomanip>
#include<stack>
#include<algorithm>
using namespace std;

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

typedef point vector;




vector operator + (vector a,vector b){return vector(a.x+b.x,a.y+b.y);}

vector operator -(vector a,vector 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||(a.x==b.x&&a.y<b.y);}

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

bool operator == (point a,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 lenth(vector a){return sqrt(dot(a,a));}

double cross(vector a,vector b){return a.x*b.y-a.y*b.x;}

double angle(vector a,vector b){return acos(dot(a,b)/lenth(a)/lenth(b));}

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;
}

double distancetoline(point p,point a,point b){//µãµ½Ö±Ïß 
	vector v1=a-b,v2=p-a;
	return (fabs(cross(v1,v2))/lenth(v1));
}

vector rotate(vector a,double rad){
	return vector(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}

double angle2(vector v){return atan2(v.y,v.x);}

struct line{
	point p;
	vector v;
	line(point p,vector v):p(p),v(v){}
};

struct circle{
	point c;
	double r;
	circle(point c=point(0,0),double r=0):c(c),r(r){}
};

void CircumscribeCircle(point p1,point p2,point p3){
	point p12=(p1+p2)/2;
	vector v12=p1-p2;
	v12=vector(v12.y,-v12.x);
	point p23=(p2+p3)/2;
	vector v23=p2-p3;
	v23=vector(v23.y,-v23.x);
	point c=getlineintersection(p12,v12,p23,v23);
	double r=lenth(p1-c);
	cout<<setiosflags(ios::fixed)<<setprecision(6)<<'('<<c.x<<','<<c.y<<','<<r<<')'<<endl;
//	return circle(c,r);
}



void inscribedcircle(point p1,point p2,point p3){
	double a=lenth(p2-p3);
	double b=lenth(p3-p1);
	double c=lenth(p1-p2);
	point p=(p1*a+p2*b+p3*c)/(a+b+c);
	cout<<setiosflags(ios::fixed)<<setprecision(6)<<'('<<p.x<<','<<p.y<<','<<distancetoline(p,p1,p2)<<')'<<endl;
//	return circle(p,distancetoline(p,p1,p2));
}

void tangentlinethroughpoint(circle C,point p){
	vector u=C.c-p;
	double dist=lenth(u);
	if(dcmp(dist-C.r)<0){
		cout<<'['<<"]"<<endl;
		return ;
	}
	else if(dcmp(dist-C.r)==0){
		u=vector(u.y,-u.x);
		double ang=atan(u.y/u.x)/3.14159265358979*180;
		if(ang<0){
			ang+=180;//changed
		}
		cout<<setiosflags(ios::fixed)<<setprecision(6)<<'['<<ang<<']'<<endl;//changed
		return ;
	}
	else{
		double ang=asin(C.r/dist);
		vector v1=rotate(u,ang);
		vector v2=rotate(u,-ang);
		double angle1=atan(v1.y/v1.x)/3.14159265358979*180;
		if(angle1<0)angle1+=180;
		double angle2=atan(v2.y/v2.x)/3.14159265358979*180;
		if(angle2<0)angle2+=180;
		if(angle2<angle1){
			double tmp=angle1;
			angle1=angle2;
			angle2=tmp;
		}
		cout<<setiosflags(ios::fixed)<<setprecision(6)<<'['<<angle1<<','<<angle2<<']'<<endl;
		return ;
	}
}

int getlinecircleintersection(line L,circle C,stack<point>& sol){//check
	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;
	double f=2*(a*b+c*d);
	double g=b*b+d*d-C.r*C.r;
	double delta=f*f-4*e*g;
	if(dcmp(distancetoline(C.c,L.p,L.v+L.p)-C.r)==0)delta=0;//L是计算出来的,不是输入的,所以可能有误差,这里去掉误差
//	cout<<"distance="<<distancetoline(C.c,L.p,L.v+L.p)<<" C.r="<<C.r<<endl;
//	cout<<"delta="<<delta<<endl;
	if(dcmp(delta)<0)return 0;
	if(dcmp(delta)==0){
		double t1=-f/(2*e);
		point p(L.p.x+t1*L.v.x,L.p.y+t1*L.v.y);
		sol.push(p);
//		cout<<'['<<'('<<p.x<<','<<p.y<<')'<<']'<<endl;
		return 1;
	}
//	cout<<"zzzzzzzzzz"<<f<<endl;
	delta=sqrt(delta);
	double t1=(-f-delta)/(2*e);
	double t2=(-f+delta)/(2*e);
	point p1(L.p.x+t1*L.v.x,L.p.y+t1*L.v.y);
	point p2(L.p.x+t2*L.v.x,L.p.y+t2*L.v.y);
	sol.push(p1);
	sol.push(p2);
//	cout<<'['<<'('<<p1.x<<','<<p1.y<<')'<<','<<'('<<p2.x<<','<<p2.y<<')'<<']'<<endl;
	return 2;
}

void circlethroughapointandtangenttoalinewithradius(point xp,point x1,point x2,double r){//check
	line xx(x1, (x2-x1) );
//	double tmp=cross(xx.p-x1,xx.v);
	double ang=atan(xx.v.y/xx.v.x);
	stack<point> sol;
	if(dcmp(ang)!=0)
	{
		double mov=r/sin(ang);
		line l1(point(x1.x-mov,x1.y),x2-x1);
		circle C(xp,r);
		int tmp=getlinecircleintersection(l1,C,sol);
		line l2(point(x1.x+mov,x1.y),x2-x1);
		tmp+=getlinecircleintersection(l2,C,sol);
		if(!tmp){cout<<'['<<']'<<endl;return ;}	
	}
	else{
		double mov=r;
		line l1(point(x1.x,x1.y+r),x2-x1);
		line l2(point(x1.x,x1.y-r),x2-x1);
		circle C(xp,r);
		int tmp=getlinecircleintersection(l1,C,sol);
		tmp+=getlinecircleintersection(l2,C,sol);
		if(!tmp){cout<<'['<<']'<<endl;return;}	
	}
	point solve[4];
	int tot=0;
	while(!sol.empty()){
		solve[tot++]=sol.top();
		sol.pop();
	}
	sort(solve,solve+tot);
	cout<<'[';
	for(int i=0;i<tot;++i){
		cout<<setiosflags(ios::fixed)<<setprecision(6)<<'('<<solve[i].x<<','<<solve[i].y<<')';
		if(i<tot-1)cout<<',';
	}
	cout<<']'<<endl;
}

void circletangenttotwolineswithradius(point x1,point x2,point x3,point x4,double r){//changed
	vector v1=x2-x1;
	vector v2=x4-x3;
	point xz=getlineintersection(x1,v1,x3,v2);
//	line L2(xz,v2);
//	line L1(xz,v1);
	point C[4];
	int tot=4;
	vector v11(-v1.y,v1.x);
	vector v22(-v2.y,v2.x);
	point xt1=xz+v11/lenth(v11)*r;
	point xt2=xz+v22/lenth(v22)*r;
	C[0]=getlineintersection(xt1,v1,xt2,v2);
	C[1]=xz+(xz-C[0]);
	point xt11=xz-v11/lenth(v11)*r;
	C[2]=getlineintersection(xt11,v1,xt2,v2);
	C[3]=xz+(xz-C[2]);
	sort(C,C+tot);
	cout<<'[';
	for(int i=0;i<4;++i){
		cout<<'('<<C[i].x<<','<<C[i].y<<')';
		if(i<3)cout<<',';
	}
	cout<<']'<<endl;
//	cout<<setiosflags(ios::fixed)<<setprecision(6)<<'['<<'('<<C1.x<<','<<C1.y<<')'<<','<<'('<<C2.x<<','<<C2.y<<')'<<','<<'('<<C3.x<<','<<C3.y<<')'<<','<<'('<<C4.x<<','<<C4.y<<')'<<']'<<endl;
}

void CircleTangentToTwoDisjointCirclesWithRadius(point p1,double r1,point p2,double r2,double rr){
	double d2=lenth(p2-p1);
	if(dcmp(d2-r1-r2-rr-rr)==0){
		point C=p1+(p2-p1)/d2*(r1+rr);
		cout<<setiosflags(ios::fixed)<<setprecision(6)<<'['<<'('<<C.x<<','<<C.y<<')'<<']'<<endl;
		return ;
	}
	else if(dcmp(d2-r1-r2-rr-rr)>0){
		cout<<'['<<']'<<endl;
		return ;
	}
	else{
		double a=rr+r2;
		double b=rr+r1;
		double c=d2;
		double ang1=acos((b*b+c*c-a*a)/2/b/c);
	//	cout<<a<<' '<<b<<' '<<c<<"cos="<<(b*b+c*c-a*a)/2/b/c<<endl;
	//	cout<<"ang1="<<ang1<<endl;
		vector vv1=rotate(p2-p1,ang1);
		double ang2=acos((a*a+c*c-b*b)/2/a/c);
		vector vv2=rotate(p1-p2,-ang2);
		point C1=getlineintersection(p1,vv1,p2,vv2);
		vv1=rotate(p2-p1,-ang1);
		vv2=rotate(p1-p2,ang2);
		point C2=getlineintersection(p1,vv1,p2,vv2);
		if(C2<C1){
			point tmp=C1;
			C1=C2;
			C2=tmp;
		}
		cout<<setiosflags(ios::fixed)<<setprecision(6)<<'['<<'('<<C1.x<<','<<C1.y<<')'<<','<<'('<<C2.x<<','<<C2.y<<')'<<']'<<endl;
		return ;
	}
}

int main(){
//	freopen("data.txt","r",stdin);
	ios::sync_with_stdio(false);
	string ind;
	while(cin>>ind){
		if(ind=="CircumscribedCircle"){
			point x1,x2,x3;
			cin>>x1.x>>x1.y>>x2.x>>x2.y>>x3.x>>x3.y;
			CircumscribeCircle(x1,x2,x3);
		}
		else if(ind=="InscribedCircle"){
			point x1,x2,x3;
			cin>>x1.x>>x1.y>>x2.x>>x2.y>>x3.x>>x3.y;
			inscribedcircle(x1,x2,x3);
		}
		else if(ind=="TangentLineThroughPoint"){
			circle C;
			point p;
			cin>>C.c.x>>C.c.y>>C.r>>p.x>>p.y;
			tangentlinethroughpoint(C,p);
		}
		else if(ind=="CircleThroughAPointAndTangentToALineWithRadius"){
			point xp,x1,x2;
			double r;
			cin>>xp.x>>xp.y>>x1.x>>x1.y>>x2.x>>x2.y>>r;
			circlethroughapointandtangenttoalinewithradius(xp,x1,x2,r);
		}
		else if(ind=="CircleTangentToTwoLinesWithRadius"){
			point x1,x2,x3,x4;
			double r;
			cin>>x1.x>>x1.y>>x2.x>>x2.y>>x3.x>>x3.y>>x4.x>>x4.y>>r;
			circletangenttotwolineswithradius(x1,x2,x3,x4,r);
		}
		else if(ind=="CircleTangentToTwoDisjointCirclesWithRadius"){
			point p1,p2;
			double r1,r2,rr;
			cin>>p1.x>>p1.y>>r1>>p2.x>>p2.y>>r2>>rr;
			CircleTangentToTwoDisjointCirclesWithRadius(p1,r1,p2,r2,rr);
		}
	}
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值