给出两圆求切线。一顿套模板,结果完全按照大白来好像过不了...
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<fstream>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define sqr(x) ((x)*(x))
#define zero(A) ((fabs(A.c.x)<eps)&&(fabs(A.c.y)<eps)&&(fabs(A.r)<eps))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const double eps=1e-10;
const double PI=4.0*atan(1.0);
int dcmp(double x)
{
if(fabs(x)<eps) return 0;
else return x<0?-1:1;
}
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y) {};
bool operator < (const Point& e) const
{
return dcmp(x - e.x) < 0 || (dcmp(x - e.x) == 0 && dcmp(y - e.y) < 0);
}
};
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); }
Vector operator -(Vector A) {return Vector(-A.x,-A.y);}
struct Circle
{
Point c;
double r;
Circle(){}
Circle(Point c,double r):c(c),r(r){}
Point point(double a)
{
return Point(c.x+cos(a)*r,c.y+sin(a)*r);
}
};
struct Line
{
Point p;
Vector v;
Line(Point p,Vector v):p(p),v(v){}
Point point(double t)
{
return p+v*t;
}
};
int getTangents(Circle A,Circle B,Point *a,Point *b)
{
int cnt=0;
if(dcmp(A.r - B.r) < 0){//不清楚这题为什么必须加这句话才能过?加了应该要换回来。
swap(A, B);
swap(a, b);
}
double d=sqrt((A.c.x-B.c.x)*(A.c.x-B.c.x)+(A.c.y-B.c.y)*(A.c.y-B.c.y));
double rdiff=fabs(A.r-B.r);
double rsum=A.r+B.r;
if(dcmp(d - rdiff) < 0) return 0;
double base=atan2(B.c.y-A.c.y,B.c.x-A.c.x);
double base2=atan2(A.c.y-B.c.y )
if(dcmp(d) == 0) return -1;
if(dcmp(d - rdiff) == 0)
{
a[cnt]=A.point(base);b[cnt]=B.point(base);cnt++;
return 1;
}
double ang=acos( abs(A.r-B.r)/d );
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(dcmp(d - rsum) == 0)
{
a[cnt]=A.point(base);
b[cnt]=B.point(PI+base);
cnt++;
}
else if(dcmp(d - rsum) > 0)
{
double ang=acos( (A.r+B.r)/d );
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;
}
double dis(Point a,Point b)
{
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
int main()
{
std::ios::sync_with_stdio(false);
Circle A, B;
while(cin>>A.c.x>>A.c.y>>A.r>>B.c.x>>B.c.y>>B.r)
{
if( zero(A)&&zero(B) ) break;
Point a[4],b[4];
int ans=getTangents(A, B,a,b);
if(ans==-1)
{
puts("-1");
continue;
}
printf("%d\n",ans);
for(int i=0;i<ans;i++)
{
for(int j=ans-1;j>i;j--)
{
if(a[j]<a[j-1] )
{
swap(a[j-1],a[j]);
swap(b[j-1],b[j]);
}
}
}
for0(i,ans)
{
printf("%.5f %.5f %.5f %.5f %.5f\n",a[i].x,a[i].y,b[i].x,b[i].y,dis(a[i],b[i]) );
}
}
return 0;
}