UVA 12304 2D Geometry 110 in 1!(与圆有关二维几何问题)

关于InscribedCircle:O是ABC内心的充要条件是:aOA+bOB+cOC=0 (均表示向量)
设ABC的坐标为:A(x1,y1),B(x2,y2),C(x3,y3) BC=a,CA=b,AB=c
内心为O(x,y)则有aOA+bOB+cOC=0(三个向量) 
MA=(x1-x,y1-y) 
MB=(x2-x,y2-y) 
MC=(x3-x,y3-y) 
则:a(x1-x)+b(x2-x)+c(x3-x)=0,a(y1-y)+b(y2-y)+c(y3-y)=0 
∴x=(ax1+bx2+cx3)/(a+b+c),Y=(ay1+by2+cy3)/(a+b+c) 
∴O((ax1+bx2+cx3)/(a+b+c),(ay1+by2+cy3)/(a+b+c))

#include<bits/stdc++.h>
using namespace std;
const double PI=acos(-1);
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 == (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));}

Vector normal(Vector A){
	double l=length(A);
	return Vector(-A.y/l,A.x/l);
}

double todistance(Point x,Point y){
	return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
}

Vector rotate(Vector A,double rad){          //rad正数时表示逆时针 负数时表示顺时针 
	return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}

double cross(Vector A,Vector B){
	return A.x*B.y-A.y*B.x;
}

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=B-A,v2=P-A;
	return fabs(cross(v1,v2)/length(v1));
}

struct Line{
	Point p;
	Vector v;
	Line(Point p,Vector v):p(p),v(v){}
	Point point(double t){return p+v*t;}
	Line move(double d){return Line(p+normal(v)*d,v); }
};


struct Circle{
	Point c;
	double r;
	Circle(){}
	Circle(Point c,double r):c(c),r(r){}
	Point point(double rad){             //圆上任意一点坐标 
		return Point(c.x+cos(rad)*r,c.y+sin(rad)*r);
	}
};

int getlinecircleintersection(Line l,Circle C,double &t1,double &t2,vector<Point>& sol){   //直线和圆相交 
	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,f=2*(a*b+c*d),g=b*b+d*d-C.r*C.r;
	double delta=f*f-4*e*g;
	if(dcmp(delta)<0) return 0; //相离
	if(dcmp(delta)==0) {
		t1=t2=-f/(2*e); sol.push_back(l.point(t1));
		return 1;
	} 
	t1=(-f-sqrt(delta))/(2*e); sol.push_back(l.point(t1));
	t2=(-f+sqrt(delta))/(2*e); sol.push_back(l.point(t2));
	return 2;

}

//计算向量极角 
double angle(Vector v){ return atan2(v.y,v.x);}

double Angle(Vector A,Vector B){
	return acos(dot(A,B)/length(A)/length(B));
}
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;

} 


int gettangents(Point p,Circle c,vector<double>& v){       //任意一点到圆的切线 
	Vector u=c.c-p;
	double dist=length(u);
	if(dist<c.r) return 0;
	else if(dcmp(dist-c.r)==0){
		v.push_back(angle(rotate(u,PI/2)));
		return 1;
	} else{
		double ang=asin(c.r/dist);
		v.push_back(angle(rotate(u,-ang)));
		v.push_back(angle(rotate(u,+ang)));
		return 2;
	}
}


int gettangents(Circle A,Circle B,Point *a,Point *b){
	int cnt=0;
	if(A.r<B.r) {swap(A,B);swap(a,b);}
	int d2=(A.c.x-B.c.x)*(A.c.x-B.c.x)+(A.c.y-B.c.y)*(A.c.y-B.c.y);
	int rdiff=A.r-B.r;
	int rsum=A.r+B.r;
	if(d2<rdiff*rdiff) return 0;      //内含 
	
	double base=atan2(B.c.y-A.c.y,B.c.x-A.c.x);
	if(d2==0 && A.r==B.r) return -1;              //无限多条 
	if(d2==rdiff*rdiff){                          //内切,1条切线 
		a[cnt]=A.point(base); 
		b[cnt]=B.point(base);
		cnt++;
		return 1;
	}	
	
	//有外公切线 
	double ang=acos((A.r-B.r)/sqrt(d2));
	a[cnt]=A.point(base+ang); b[cnt]=B.point(base+ang); cnt++;
	a[cnt]=A.point(base-ang); b[cnt]=B.point(base-ang); cnt++;
	if(d2==rsum*rsum){
		a[cnt]=A.point(base);
		b[cnt]=B.point(PI+base); 
		cnt++;
	}
	else if(d2>rsum*rsum){
		double ang=acos((A.r+B.r)/sqrt(d2));
		a[cnt]=A.point(base+ang); b[cnt]=B.point(PI+base+ang);cnt++;
		a[cnt]=A.point(base-ang); b[cnt]=B.point(PI+base-ang);cnt++;
	}
	return cnt;
}


void CircumscribedCircle(){        //1
	Point p[3];
	for(int i=0;i<3;i++)
	scanf("%lf %lf",&p[i].x,&p[i].y);
	
	Point o=getlineintersection((p[0]+p[1])/2,rotate(p[1]-p[0],PI/2),(p[0]+p[2])/2,rotate(p[2]-p[0],PI/2));
	printf("(%.6lf,%.6lf,%.6lf)\n",o.x,o.y,todistance(o,p[0]));
}

void InscribedCircle(){
	Point p1,p2,p3;
	scanf("%lf%lf%lf%lf%lf%lf", &p1.x, &p1.x,&p2.x,&p2.y,&p3.x,&p3.y);
	double a=length(p2-p3);
	double b=length(p3-p1);
	double c=length(p1-p2);
	Point p=(p1*a+p2*b+p3*c)/(a+b+c);
	printf("(%.6lf,%.6lf,%.6lf)\n",p.x,p.y,distancetoline(p,p1,p2));
}

void TangentLineThroughPoint(){
	Circle c;
	Point p;
	vector<double> v;
	scanf("%lf %lf %lf",&c.c.x,&c.c.y,&c.r);
	scanf("%lf %lf",&p.x,&p.y);
	printf("[");
	if(gettangents(p,c,v)){
		sort(v.begin(),v.end());
		printf("%.6lf",v[1]);
	}
	if(v.size()==2) printf("%.6lf",v[2]);
	printf("]\n");
	
}

double t1,t2;
void CircleThroughAPointAndTangentToALineWithRadius(){
	Circle c;
	Point p1,p2;
	scanf("%lf%lf%lf%lf%lf%lf%lf",&c.c.x,&c.c.y,&p1.x,&p1.y,&p2.x,&p2.y,&c.r);
	
	
	Point a1=p1+normal(p2-p1)*c.r;
	Point a2=p1-normal(p2-p1)*c.r;
	vector<Point> poi;
	poi.clear();
	Line l1(a1,p2-p1),l2(a2,p2-p1);
	int num=getlinecircleintersection(l1,c,t1,t2,poi);
	num+=getlinecircleintersection(l2,c,t1,t2,poi);
	
	printf("[");
    for(int i=0;i<num;i++)
	{
        if(i!=0) printf(",");
        printf("(%.6f,%.6f)",poi[i].x,poi[i].y);
    }
        printf("]\n");
}


inline Point e_to_go(Vector A, double len) { return A / length(A) * len; }

 void CircleTangentToTwoLinesWithRadius()
 {
     Point A, B, C ,D;
    double r;
    scanf("%lf%lf %lf%lf %lf%lf %lf%lf %lf", &A.x, &A.y, &B.x, &B.y, &C.x, &C.y, &D.x, &D.y, &r);

     vector<Point> v;
     int control = cross(B - A, D - C) < 0 ? -1 : 1;

     Point P = getlineintersection(A, B-A, C, D-C);
     double seta = Angle(B - A, D - C)/2;
     Vector v1 = rotate(B - A, control*seta);
     Vector v2 = rotate(B - A, -control*(PI/2 - seta));

     v.push_back(P + e_to_go(v1, r/sin(seta)));
     v.push_back(P - e_to_go(v1, r/sin(seta)));
     v.push_back(P + e_to_go(v2, r/cos(seta)));
     v.push_back(P - e_to_go(v2, r/cos(seta)));
     sort(v.begin(), v.end());
 
     for (int i = 0; i < v.size(); i++)
         printf("%c(%.6lf,%.6lf)", ",["[i == 0], v[i].x, v[i].y);
     printf("]\n");
 }

void CircleTangentToTwoDisjointCirclesWithRadius(){
	Circle c1,c2;
	double r;
	scanf("%lf%lf%lf %lf%lf%lf %lf", &c1.c.x, &c1.c.y, &c1.r, &c2.c.x, &c2.c.y, &c2.r, &r);
    c1.r += r, c2.r += r;
	vector<Point> v;
	getcirclecircleintersection(c1,c2,v);
	sort(v.begin(), v.end());
 
    if (!v.size())    printf("[");
    for (int i = 0; i < v.size(); i++)
        printf("%c(%.6lf,%.6lf)", ",["[i == 0], v[i].x, v[i].y);
     	printf("]\n");
}
	

string s;
int main(){
	while(cin>>s){
		if(s=="CircumscribedCircle")
		CircumscribedCircle();
		else if(s=="InscribedCircle"){
			InscribedCircle();
		}
		else if(s=="TangentLineThroughPoint")
		TangentLineThroughPoint();
		else if(s=="CircleThroughAPointAndTangentToALineWithRadius")
		CircleThroughAPointAndTangentToALineWithRadius();
		else if(s=="CircleTangentToTwoLinesWithRadius")
		CircleTangentToTwoLinesWithRadius();
		else if(s=="CircleTangentToTwoDisjointCirclesWithRadius")
		CircleTangentToTwoDisjointCirclesWithRadius();
	}
	return 0;		
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值