bool Getccinte(Circle c1,Circle c2,Point &a,Point &b) { double d = Length(c1.c-c2.c); if(dcmp(d)==0||dcmp(c1.r+c2.r-d)<0||dcmp(fabs(c1.r-c2.r)-d)>0) return 0; double ang = Angle(c2.c-c1.c); double da = acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d)); a = c1.point(ang-da),b = c1.point(ang+da); return 1; }
// 两圆切线,-1无穷 // a[i]和b[i]分别是第i条切线在圆A和圆B上的切点 int getTangents(Circle& A,Circle& B,Point* a,Point* b) { int cnt=0; if (A.r<B.r) {swap(A,B);swap(a,b);} int d2=(A.c.x-B.c.x)*(A.c.x-B.c.x)+(A.c.y-B.c.y)*(A.c.y-B.c.y); int rdiff=A.r-B.r; int rsum=A.r+B.r; if (d2<rdiff*rdiff) return 0; double base=atan2(B.c.y-A.c.y,B.c.x-A.c.x); if (d2==0 && A.r==B.r) return -1; if (d2==rdiff*rdiff) { a[cnt]=A.point(base);b[cnt]=B.point(base);cnt++; return 1; } // 外切 double ang=acos((A.r-B.r)/sqrt(d2)); a[cnt]=A.point(ang+base);b[cnt]=B.point(ang+base);cnt++; a[cnt]=A.point(base-ang);b[cnt]=B.point(base-ang);cnt++; if (d2==rsum*rsum) { a[cnt]=A.point(base);b[cnt]=B.point(acos(-1)+base+ang);cnt++; } else if (d2>rsum*rsum) { double ang=acos((A.r+B.r)/sqrt(d2)); 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; }
/* a[i] 和 b[i] 分别是第i条切线在O1和O2上的切点 */ int getTangents (Circle o1, Circle o2, Point* a, Point* b) { int cnt = 0; if (o1.r < o2.r) { swap(o1, o2); swap(a, b); } double d2 = getLength(o1.o - o2.o); d2 = d2 * d2; double rdif = o1.r - o2.r, rsum = o1.r + o2.r; if (d2 < rdif * rdif) return 0; if (dcmp(d2) == 0 && dcmp(o1.r - o2.r) == 0) return -1; double base = getAngle(o2.o - o1.o); if (dcmp(d2 - rdif * rdif) == 0) { a[cnt] = o1.point(base); b[cnt] = o2.point(base); cnt++; return cnt; } double ang = acos( (o1.r - o2.r) / sqrt(d2) ); a[cnt] = o1.point(base+ang); b[cnt] = o2.point(base+ang); cnt++; a[cnt] = o1.point(base-ang); b[cnt] = o2.point(base-ang); cnt++; if (dcmp(d2 - rsum * rsum) == 0) { a[cnt] = o1.point(base); b[cnt] = o2.point(base); cnt++; } else if (d2 > rsum * rsum) { double ang = acos( (o1.r + o2.r) / sqrt(d2) ); a[cnt] = o1.point(base+ang); b[cnt] = o2.point(base+ang); cnt++; a[cnt] = o1.point(base-ang); b[cnt] = o2.point(base-ang); cnt++; } return cnt; }
// 两圆相交 int getCircleCircleIntersection(Circle& C1, Circle& C2, vector<Point>& sol) { double d = Length(C1.c - C2.c); if(dcmp(d) == 0) { if(dcmp(C1.r - C2.r) == 0) return -1; // 重合,无穷多交点 return 0; } if(dcmp(C1.r + C2.r - d) < 0) return 0; if(dcmp(fabs(C1.r-C2.r) - d) > 0) return 0; double a = angle(C2.c - C1.c); double da = acos((C1.r*C1.r + d*d - C2.r*C2.r) / (2*C1.r*d)); Point p1 = C1.point(a-da), p2 = C1.point(a+da); sol.push_back(p1); if(p1 == p2) return 1; sol.push_back(p2); return 2; }
/* 圆和圆的交点 */ int getCircleCircleIntersection (Circle o1, Circle o2, vector<Point>& sol) { double d = getLength(o1.o - o2.o); if (dcmp(d) == 0) { if (dcmp(o1.r - o2.r) == 0) return -1; return 0; } if (dcmp(o1.r + o2.r - d) < 0) return 0; if (dcmp(fabs(o1.r-o2.r) - d) > 0) return 0; double a = getAngle(o2.o - o1.o); double da = acos((o1.r*o1.r + d*d - o2.r*o2.r) / (2*o1.r*d)); Point p1 = o1.point(a-da), p2 = o1.point(a+da); sol.push_back(p1); if (p1 == p2) return 1; sol.push_back(p2); return 2; }
//返回切线的条数,-1表示无穷条切线 //a[i]和b[i]分别是第i条切线在圆A和圆B上的切点。内切,外切时,这两个点相同 int getTangents(Circle A, Circle B, Point* a, Point* b){ int cnt = 0; if(A.r < B.r){ swap(A, B); swap(a, b); } double d2 = (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 = A.r - B.r; double rsum = A.r + B.r; if(dcmp(d2 - rdiff*rdiff) < 0) // 内含 return 0; double base = atan2(B.c.y-A.c.y, B.c.x-A.c.x); if(dcmp(d2)==0 && dcmp(A.r-B.r)==0)// 无限多条切线 return -1; if(dcmp(d2-rdiff*rdiff) == 0){// 内切,一条切线 a[cnt] = A.point(base); b[cnt] = B.point(base); cnt++; return 1; } double ang = acos((A.r-B.r)/sqrt(d2));// 两条外公切线 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(d2-rsum*rsum) == 0){ a[cnt] = A.point(base); b[cnt] = B.point(PI + base); cnt++; } else if(dcmp(d2 - rsum*rsum) > 0){ // 两条内公切线 double ang = acos((A.r+B.r) / sqrt(d2)); 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; }