点到圆的切点

点到圆的切点
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);
}
原文地址:https://www.cnblogs.com/LaiYiC/p/15272771.html