int TwoCircleTangents(Circle A,Circle B,vector<Point>& a,vector<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.push_back(A.getPoint(base)) ; b.push_back(B.getPoint(base)); cnt++; return 1; } double ang = acos((A.r-B.r) / sqrt(d2)); a.push_back(A.getPoint(base+ang)); b.push_back(B.getPoint(base+ang)); cnt++; a.push_back(A.getPoint(base-ang)); b.push_back(B.getPoint(base-ang)); cnt++; if(d2 == rsum*rsum) { a.push_back(A.getPoint(base)); b.push_back(B.getPoint(PI+base)); cnt++; } else if(d2 > rsum*rsum) { double ang = acos((A.r+B.r) / sqrt(d2)); a.push_back(A.getPoint(base+ang)); b.push_back(B.getPoint(PI+base+ang)); cnt++; a.push_back(A.getPoint(base-ang)); b.push_back(B.getPoint(PI+base-ang)); cnt++; } return cnt; }
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.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y); int rdiff = A.r-B.r; int rsum = A.r+B.r; if(d2 < rdiff*rdiff) return 0; double base = atan2(B.y-A.y, B.x-A.x); if(d2 == 0 && A.r == B.r) return -1; // 无限多条切线 if(d2 == rdiff*rdiff) { // 内切,1条切线 a[cnt] = A.getPoint(base); b[cnt] = B.getPoint(base); cnt++; return 1; } // 有外共切线 double ang = acos((A.r-B.r) / sqrt(d2)); a[cnt] = A.getPoint(base+ang); b[cnt] = B.getPoint(base+ang); cnt++; a[cnt] = A.getPoint(base-ang); b[cnt] = B.getPoint(base-ang); cnt++; if(d2 == rsum*rsum) { // 一条内共切线 a[cnt] = A.getPoint(base); b[cnt] = B.getPoint(PI+base); cnt++; } else if(d2 > rsum*rsum) { // 两条内共切线 double ang = acos((A.r+B.r) / sqrt(d2)); a[cnt] = A.getPoint(base+ang); b[cnt] = B.getPoint(PI+base+ang); cnt++; a[cnt] = A.getPoint(base-ang); b[cnt] = B.getPoint(PI+base-ang); cnt++; } return cnt; }
int TwoCirclePoint(Circle C1,Circle C2,vector<Point>& res) //求2圆交点,返回交点数(特别的-1表示2圆重合,无穷个交点) { 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.getPoint(a-da),p2 = C1.getPoint(a+da); res.push_back(p1); if(p1 == p2) return 1; res.push_back(p2); return 2; }
void showTemplate(const MinutiaeTemplate & mt, double T, const char *name) { Circle c; c.setT(T); c.getCenter(mt); c.fromTemplate(mt); Mat mat(500, 500, CV_8UC3, Scalar(255, 255, 255)); int offsetx = 100, offsety = 100, R = c.getR(); circle(mat,Point(c.getCenterX()+offsetx,c.getCenterY()+offsety),R,Scalar(0,255,0)); for(int i = 1; i < c.getSize(); i+=2) { double p1 = c.getPoint(i-1); double p2 = c.getPoint(i); line(mat,Point(R*cos(p1)+c.getCenterX()+offsetx,R*sin(p1)+c.getCenterY()+offsety), Point(R*cos(p2)+c.getCenterX()+offsetx,R*sin(p2)+c.getCenterY()+offsety), Scalar(255,0,0)); } for(int i = 0; i < mt.getSize(); i++) circle(mat,Point(mt.getMinutia(i).getX()+offsetx,mt.getMinutia(i).getY()+offsety),3,Scalar(0,0,255),CV_FILLED); imshow(name,mat); }