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