【圆的反演变换】hdu4773

这个blog解释的挺不错:http://blog.csdn.net/acdreamers/article/details/16966369

给定不相交的两个圆以及圆外一点,找一个经过给定点的圆与其他两个圆相切

首先来看反演变换,首先是给定一个圆圆心为O,半径为R

1、圆外一点P与圆内一点P‘会一一对应的反演OP*OP'=R*R

2、经过O的圆,反演后成为不经过O的一条直线

3、不经过O的圆,反演后成为另一个圆,且圆心并不对应

4、不经过O的直线反演后成为一个经过O的圆

5、过O的直线反演后不变

那么这道题就把两个圆反演之后求两圆的公切线,然后反演回去,就会成为一个过O的圆,且与另两圆相切(由反演的过程可看出)

求反演后的圆的圆心,可以将过O的直线所在的那条直径两端点反演,然后再求圆心

这道题貌似不需要求内公切线,且反演中心圆的半径要设大一点,否则会有精度问题

#include 
#include 	
#include 
#include 
#include 
#include 
#define sqr(x) ((x)*(x))
using namespace std;
const double eps=1e-10;
struct Point{
	double x,y,z;
	Point operator +(const Point &b) const;
	Point operator *(const double &b) const;
	Point operator -() const; 
	double dist() const 
	{
		return sqrt(x*x+y*y);
	}
	void print() const 
	{
		printf("COR=(%.3lf,%.3lf)\n",x,y);
	}
}P;
struct Circle{
	Point o;
	double r;
	void print() const
	{
		o.print();
		printf("R=%.3lf\n\n",r);
	}
}C1,C2;
struct Line{
	Point p1,p2;
	void print() const
	{
		p1.print();
		p2.print();
		printf("\n");
	}
}st[4];
int tot;
void cross(Point &p,Point e,Point r)
{
	p.x=e.y*r.z-e.z*r.y;
	p.y=e.z*r.x-e.x*r.z;
	p.z=e.x*r.y-e.y*r.x;
}
double dot(Point l,Point P)
{
	return l.x*P.x+l.y*P.y+l.z*P.z;
}
Point Point::operator +(const Point &b) const
{
	Point c;
	c.x=x+b.x,c.y=y+b.y;
	return c;
}
Point Point::operator *(const double &b) const
{
	Point c;
	c.x=x*b,c.y=y*b;
	return c;
}
Point Point::operator -() const
{
	Point c;
	c.x=-x,c.y=-y;
	return c;
}
Point inverse_Point(Point P,Point A)
{
	Point PA=A+(-P);
	double len=1000000.0/PA.dist();
	Point A1=P+PA*(len/PA.dist());
	return A1;
}
Circle inverse_Circle(Point P,Circle C)
{
	Point O=C.o,A,B,A1,B1;
	Point PO=O+(-P);
	A=P+PO*((PO.dist()-C.r)/PO.dist());
	B=P+PO*((PO.dist()+C.r)/PO.dist());
	A1=inverse_Point(P,A);
	B1=inverse_Point(P,B);
	Circle C1;
	C1.o=(A1+B1)*0.5;
	C1.r=((A1+(-B1)).dist())*0.5;
	return C1;
}
int CircleCrossCircle( Point p1 , double r1 , Point p2 , double r2 , Point &cp1 , Point &cp2 ){
	double mx = p2.x - p1.x , sx = p2.x+p1.x , mx2 = mx*mx;
	double my = p2.y - p1.y , sy = p2.y+p1.y , my2 = my*my;
	double sq = mx2 + my2 , d = -( sq - sqr ( r1-r2 ) ) * ( sq - sqr ( r1+r2 ) ) ;
	if ( d+eps <0 ) return 0 ; if ( deps ) return 2 ; else return 1 ;
}
void Add_line(Point cp1,Circle C1,Circle C2,double e)
{
	Point pp;
	pp=(cp1+(-C2.o));
	++tot;
	st[tot].p1=C2.o+pp*(C2.r/pp.dist());
	st[tot].p2=C1.o+pp*(C1.r/pp.dist())*e;
}
void Cut(Circle C1,Circle C2)
{
	Circle CC,C3;
	CC.o=(C1.o+C2.o)*0.5;
	CC.r=((CC.o+(-C1.o)).dist());
	if (C1.r-C2.r>-eps) {
		Circle e;
		e=C1,C1=C2,C2=e;
	}
	C3=C2,C3.r=C2.r-C1.r;
	Point cp1,cp2;
	int tmp;
	if ((tmp=CircleCrossCircle(CC.o,CC.r,C3.o,C3.r,cp1,cp2)) || (fabs(C3.r)


你可能感兴趣的:(计算几何,hdu,数学)