求两个圆公切线的模板

// 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;
}
假设有两个心分别为 $(x_1, y_1)$ 和 $(x_2, y_2)$,半径分别为 $r_1$ 和 $r_2$。以下是求解两个公切线Python 代码: ``` python import math def find_tangent_lines(x1, y1, r1, x2, y2, r2): dist = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) if dist < abs(r2 - r1): return [] # 内含,无公切线 elif dist == abs(r2 - r1): # 外切,一条切线 xt = x1 + r1 * (x2 - x1) / dist yt = y1 + r1 * (y2 - y1) / dist return [(xt, yt, xt + y2 - y1, yt + x1 - x2)] else: # 两条外公切线 angle = math.acos((r1 - r2) / dist) x_diff = x2 - x1 y_diff = y2 - y1 x_1 = x1 + r1 * (x_diff * math.cos(angle) + y_diff * math.sin(angle)) / dist y_1 = y1 + r1 * (y_diff * math.cos(angle) - x_diff * math.sin(angle)) / dist x_2 = x1 + r1 * (x_diff * math.cos(-angle) + y_diff * math.sin(-angle)) / dist y_2 = y1 + r1 * (y_diff * math.cos(-angle) - x_diff * math.sin(-angle)) / dist x_3 = x2 + r2 * (x_diff * math.cos(angle) - y_diff * math.sin(angle)) / dist y_3 = y2 + r2 * (y_diff * math.cos(angle) + x_diff * math.sin(angle)) / dist x_4 = x2 + r2 * (x_diff * math.cos(-angle) - y_diff * math.sin(-angle)) / dist y_4 = y2 + r2 * (y_diff * math.cos(-angle) + x_diff * math.sin(-angle)) / dist return [(x_1, y_1, x_3, y_3), (x_2, y_2, x_4, y_4)] ``` 该函数返回一个包含两个元组的列表,每个元组代表一条公切线,格式为 $(x_1, y_1, x_2, y_2)$,其中 $(x_1, y_1)$ 和 $(x_2, y_2)$ 分别为一条公切线两个端点。如果两个没有公切线,则返回空列表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值