点到圆的切点
https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/7/CGL_7_F
int sgn(double x) {
if(fabs(x)<eps)return 0;
return x<0?-1:1;
}
struct Point { //定义点和基本运算
double x,y;
double ang;
Point() {}
Point(double x,double y):x(x),y(y) {}
Point operator + (Point B) {
return Point(x+B.x,y+B.y);
}
Point operator - (Point B) {
return Point(x-B.x,y-B.y);
}
Point operator * (double k) {
return Point(x*k,y*k); //长度增大k倍
}
Point operator / (double k) {
return Point(x/k,y/k); //长度缩小k倍
}
bool operator == (Point B) {
return sgn(x-B.x)==0 && sgn(y-B.y)==0;
}
double operator ^(Point B) {
return x*B.y-y*B.x;
}
double distance(Point p) {
return hypot(x-p.x,y-p.y);
}
};
typedef Point Vector;
double Cross(Vector A,Vector B) {
return A.x*B.y - A.y*B.x; //叉积
}
struct Line {
Point p1,p2;//线上的两个点
Line() {}
Line(Point p1,Point p2):p1(p1),p2(p2) {}
};
struct Circle {
Point c;//圆心
double r;//半径
Circle() {}
Circle(Point c,double r):c(c),r(r) {}
Circle(double x,double y,double _r) {
c=Point(x,y);
r = _r;
}
};
/**********************************/
double Distance(Point A, Point B) {
return hypot(A.x-B.x,A.y-B.y);
}
Point rotate(Point base,Point a,double r) { //旋转
Point b=a-base;
a.x=b.x*cos(r)-b.y*sin(r);
a.y=b.x*sin(r)+b.y*cos(r);
a=a+base;
return a;
}
void tangent_points(Circle c,Point p,Point &p1,Point &p2) {
Vector v=p-c.c;
double d = Distance(p,c.c);
double r=acos(c.r/d);
v=v*c.r/d;
p1=rotate(c.c,c.c+v,r);
p2=rotate(c.c,c.c+v,-r);
}/**********************************************/
void work() {
Circle a;
Point p;
scanf("%lf%lf",&p.x,&p.y);
scanf("%lf%lf%lf",&a.c.x,&a.c.y,&a.r);
Point p1,p2;
tangent_points(a,p,p1,p2);
if(sgn(p1.x-p2.x)>0)swap(p1,p2);
else if(sgn(p1.x-p2.x)==0 && sgn(p1.y-p2.y)>0)swap(p1,p2);
printf("%lf %lf
",p1.x,p1.y);
printf("%lf %lf
",p2.x,p2.y);
}