求两个圆公切线的模板

// a[i] 和 b[i]存放第 i 条公切线与 圆A 和 园B 的交点
// 返回值为切线的条数 如果没有切线返回值为-1
int getTangents(circle A, circle B, Point*a, Point *b){
    int cnt = 0;
    // 以A为半径更大的那个圆进行计算
    if(A.r < B.r) return getTangents(B, A, b, a);
    db d2 = (A.p-B.p).len2();  // 圆心距平方
    db rdiff = A.r - B.r;		// 半径差
    db rsum = A.r + B.r;		//半径和
    if(d2 < rdiff * rdiff) return 0; 	// 情况1,内含,没有公切线
    Vector AB = B.p - A.p;				// 向量AB,其模对应圆心距
    db base = atan2(AB.y, AB.x);		// 求出向量AB对应的极角
    if(d2 == 0 && A.r == B.r) return -1;// 情况3,两个圆重合,无限多切线
    if(d2 == rdiff * rdiff){ 			// 情况2,内切,有一条公切线
        a[cnt] = A.point(base);			
        b[cnt] = B.point(base);cnt++;
        return 1;
    }
    // 求外公切线
    db 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(d2 == rsum * rsum){  // 情况5,外切,if里面求出内公切线
        a[cnt] = A.point(base); b[cnt] = B.point(pi+base); cnt++;
    }
    else if(d2 > rsum * rsum){	//情况6,相离,再求出内公切线
        db 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++;
    }
    // 此时,d2 < rsum * rsum 代表情况 4 只有两条外公切线
    return cnt;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值