#include using namespace std; typedef long long ll; templatebool chmax(T &a, const T &b) { if (abool chmin(T &a, const T &b) { if (b #define vl vector #define vii vector> #define vll vector> #define vvi vector> #define vvl vector> #define vvii vector>> #define vvll vector>> #define vst vector #define pii pair #define pll pair #define pb push_back #define all(x) (x).begin(),(x).end() #define mkunique(x) sort(all(x));(x).erase(unique(all(x)),(x).end()) #define fi first #define se second #define mp make_pair #define si(x) int(x.size()) const int mod=998244353,MAX=300005,INF=15<<26; //幾何ライブラリ // define double ll をするときは Point の < と == も書き換えよう! const double eps=1e-8; const double pi=acos((double)-1.0L); #define equals(a,b) (fabs((a)-(b))eps) return counter_clockwise; if(cross(a,b)<-eps) return clockwise; if(dot(a,b)<-eps) return online_back; if(a.norm()r2){ if(d<(r1-r2)) return 2; } if(d<=r1+r2) return 0; else return 3; } pair segCrossPpoints(Circle c,Line l){ //assert(intersect(c,l)); Vector pr=project(l,c.c); Vector e=(l.p2-l.p1)/abs(l.p2-l.p1); double base=sqrt(c.r*c.r-norm(pr-c.c)); return make_pair(pr+e*base,pr-e*base); } double arg(Vector p){return atan2(p.y,p.x);} Vector polar(double a,double r){return Point(cos(r)*a,sin(r)*a);} //inside(outside) pair getCrossPoints(Circle c1,Circle c2){ //assert(intersect(c1,c2)); double d=abs(c1.c-c2.c); double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d)); double t=arg(c2.c-c1.c); return make_pair(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a)); } vector Commontangent(Circle c1,Circle c2){ vector res; Point p=c2.c-c1.c; if(abs(p)>=(c1.r+c2.r)){ Point a,b; a.x=c1.r*(p.x*(c1.r+c2.r)+p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p); a.y=c1.r*(p.y*(c1.r+c2.r)-p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p); b.x=c1.r*(p.x*(c1.r+c2.r)-p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p); b.y=c1.r*(p.y*(c1.r+c2.r)+p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p); res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}}); if(!(a==b)){ res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}}); } } if(abs(p)>=abs(c1.r-c2.r)){ Point a,b; a.x=c1.r*(p.x*(c1.r-c2.r)+p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p); a.y=c1.r*(p.y*(c1.r-c2.r)-p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p); b.x=c1.r*(p.x*(c1.r-c2.r)-p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p); b.y=c1.r*(p.y*(c1.r-c2.r)+p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p); res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}}); if(!(a==b)){ res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}}); } } return res; } typedef vector Polygon; /* IN 2 ON 1 OUT 0 */ int contains(Polygon g,Point p){ int n=int(g.size()); bool x=false; for(int i=0;ib.y) swap(a,b); if(a.y=2&&ccw(u[j-2],u[j-1],s[i])==counter_clockwise;j--){ u.pop_back(); } u.push_back(s[i]); } for(int i=int(s.size())-3;i>=0;i--){ for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])==counter_clockwise;j--){ l.pop_back(); } l.push_back(s[i]); } } if(!ok){ for(int i=2;i=2&&ccw(u[j-2],u[j-1],s[i])!=clockwise;j--){ u.pop_back(); } u.push_back(s[i]); } for(int i=int(s.size())-3;i>=0;i--){ for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])!=clockwise;j--){ l.pop_back(); } l.push_back(s[i]); } } reverse(all(l)); for(int i=int(u.size())-2;i>=1;i--) l.push_back(u[i]); return l; }//ok==1なら辺の上も含める Polygon convex_cut(const Polygon& P, const Line& l) { Polygon Q; for(int i=0;i perpendicular_bisector(Point a,Point b){ Point c=(a+b)/2; Vector v=b-c; swap(v.x,v.y); v.x*=-1; Point p=c; if(v.x==0){ v.y=1; p.y=0; } else if(v.y==0){ v.x=1; p.x=0; } else{ if(v.x<0){ v.x*=-1; v.y*=-1; } ll g=gcd(abs(ll(v.x)),abs(ll(v.y))); v.x/=g; v.y/=g; if(p.x>=0){ ll d=p.x/v.x; p=p-v*d; }else{ ll d=abs(p.x)/v.x; p=p+v*d; if(p.x<0){ p=p+v; } } } return mp(p,v); } //2倍するなりして整数にしておくこと /* Line perpendicular_bisector(Point a,Point b){ Point c=(a+b)/2; Point d=turn(a,c,M_PI/2.0); return {c,d}; } //2倍するなりして整数にしておくこと */ pair angle_bisector(Line a,Line b){ // assert(!isParallel(a,b)); Point p=getCrossPointL(a,b); if(a.p1==p) swap(a.p1,a.p2); if(b.p1==p) swap(b.p1,b.p2); double kaku1=arg(a.p1-p); double kaku2=arg(b.p1-p); return mp(Line{p,p+polar(1.0,(kaku1+kaku2)/2.0)},Line{p,p+polar(1.0,(kaku1+kaku2+M_PI)/2.0)}); } Line abc_to_line(double a,double b,double c){ if(a==0){ if(b==0){ if(c>=0){ return {{-INF,-INF},{INF,-INF}}; }else{ return {{-INF,INF},{INF,INF}}; } }else if(b>0){ return {{0,-c/b},{1,-c/b}}; }else{ return {{1,-c/b},{0,-c/b}}; } }else if(a>0){ if(b==0){ return {{-c/a,1},{-c/a,0}}; }else{ if(b>0){ return {{0,-c/b},{1,-(a+c)/b}}; }else{ return {{1,-(a+c)/b},{0,-c/b}}; } } }else{ if(b==0){ return {{-c/a,0},{-c/a,1}}; }else{ if(b>0){ return {{0,-c/b},{1,-(a+c)/b}}; }else{ return {{1,-(a+c)/b},{0,-c/b}}; } } } } // ax+by+c>=0 convex_cut用の2点 // a=b=0のときは雑にINF int main(){ std::ifstream in("text.txt"); std::cin.rdbuf(in.rdbuf()); cin.tie(0); ios::sync_with_stdio(false); int Q;cin>>Q; while(Q--){ Circle c1,c2; cin>>c1.c.x>>c1.c.y>>c1.r; cin>>c2.c.x>>c2.c.y>>c2.r; auto res=Commontangent(c1,c2); //cout<