求两圆的公切线计算

关于两圆的公切线计算我们首先需要搞清楚的是两个圆之间有哪些位置关系,两个圆的位置包括内含、内切、外切、外离几种方式,可以看出位置关系可以根据“两圆心之间的距离”与“两圆半径和”以及“两圆半径差”之间的关系判断。

 

 

假设大圆半径为R,小圆半径为 r, 把“两圆心之间的距离”表示为d, “两圆半径和”表示为s, “两圆半径差”表示为x,那么:

d = |R + r|;

x = |R - r|;

可以得出各位置关系必须满足以下相应条件:

内含:    d > 0 && d < x

内切:    d  > 0 && d = x

外切:    d = s

外离:    d > s

从图中我们也可以看出不同位置关系的公切线分布情况

内切位置的公切线比较容易求解,而外切、外离位置情况下公切线求解是相对复杂的,这次主要分析如何求出处于外离位置关系的两圆之间的公切线。

首先,我们先分析如何求解外公切线;

如图所示(1.以下角度均是用弧度值表示;2. 为了方便,假设有P、Q两点, 则两点之间的朝向暂用Hpq表示 ):

cosα =|PA| / |PQ| = (|PB| - |AB|) / |PQ|  =  (|R-r|) / d    ->   α = acos ( (|R-r|) / d )

Hpq = atan( (y1-y0)/(x1-x0) )

Hpb = Hpq + α     同理 Hpc = Hpq - α 

Hbe = Hpb - PI/2

Hcd = Hpc + PI/2

若两条切线的斜率分别用k1、k2表示, 那么

k1 = tan(Hbe);  k2 = tan(Hcd)

通过距离和朝向我们可以计算出距离直线某点的另一个点, 从而求出切点,比如B(x3, y3)和E(x4, y4)这两个点, 

x3 = x0 + R * cos(Hpb)

y3 = y0 + R * sin(Hpb)

 

x4 = x1 + r * cos(Hpb)

y4 = y1 + r * sin(Hpb)

同理我们可以去求点C和D

最后,知道斜率以及直线上的任意一个点就可以求出直线方程了;

 

下边再来分析如何求解两条交叉公切线:

 

如图,求解交叉公切线主要利用对角三角形对应边成比例的思想求出边L,然后就和上边求外公切线一样,求出α的值就可以顺利求出切线方程

假设|PQ|长度为d, 那么 L / (d-L)  = R / r     ->    L = dR / (R +r)

cosα = |PA| / L = R / L =(R + r) / d      ->  α = acos( (R+r) / d )

 

Hpq = atan( (y1-y0)/(x1-x0) )

Hpa = Hpq + α     同理 Hpb = Hpq - α 

Had = Hpa - PI/2

Hbc = Hpb + PI/2

若两条切线的斜率分别用k1、k2表示, 那么

k1 = tan(Had);  k2 = tan(Hbc)

通过距离和朝向我们可以计算出距离直线某点的另一个点, 从而求出切点,比如A(x2, y2)和D(x3, y3)这两个点, 

x2 = x0 + R * cos(Hpa)

y2 = y0 + R * sin(Hpa)

 

x3 = x1 + r * cos(Hpa + PI)

y3 = y1 + r * sin(Hpa + PI)

同理我们可以去求点B和C

最后,知道斜率以及直线上的任意一个点就可以求出直线方程了;

 

以上就是我求相离位置关系的两圆公切线的基本思路,因为不是很方便表示,可能有的地方不是很清楚,敬请见谅,仅供参考。

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现两圆公切线交点计算,需要先判断两个圆是否有公切线,如果有,则可以根据两圆心和半径计算两个切点坐标。 假设两个圆分别为圆A和圆B,圆心坐标分别为(xa,ya)和(xb,yb),半径分别为ra和rb。如果两个圆有公切线,则公切线与两个圆的切点坐标分别为(x1,y1)和(x2,y2)。 首先,根据两圆心之间的距离d,判断两个圆是否有公切线: 1. d > ra + rb,两个圆外离,无公切线; 2. d < |ra - rb|,一个圆包含在另一个圆内,无公切线; 3. d = 0,两圆重合,无公切线; 4. 其他情况,两圆相交,有公切线。 如果存在公切线,则可以根据两个圆心和半径计算切点坐标: 1. 两圆心的连线斜率k和截距b; 2. 以圆A的圆心为起点,向切点方向移动ra个单位长度,切点坐标(x1,y1); 3. 以圆B的圆心为起点,向切点方向移动rb个单位长度,切点坐标(x2,y2)。 下面是C++代码实现: ```cpp #include <iostream> #include <cmath> using namespace std; // 判断两个浮点数是否相等 bool isEqual(double a, double b) { return fabs(a - b) < 1e-6; } // 计算两圆公切线交点 bool getTangentialPoints(double xa, double ya, double ra, double xb, double yb, double rb, double &x1, double &y1, double &x2, double &y2) { double d = sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb)); // 两圆心之间的距离 if (isEqual(d, 0) || d > ra + rb || d < fabs(ra - rb)) { // 两圆重合或相离或包含,无公切线 return false; } double A = (ra - rb + d) * (ra + rb - d) * (ra + rb + d) * (ra - rb - d); double B = 2 * (ra + rb + d) * (ra + rb - d) * (rb - ra + d) * (ra - rb + d); double C = (ra + rb + d) * (ra - rb - d) * (ra - rb + d) * (rb - ra + d); double x3 = (xa + xb) / 2.0 + (xb - xa) * (ra * ra - rb * rb) / (2.0 * d * d); double y3 = (ya + yb) / 2.0 + (yb - ya) * (ra * ra - rb * rb) / (2.0 * d * d); if (isEqual(A, 0) && isEqual(B, 0)) { // 两圆相切,只有一条公切线 x1 = x3; y1 = y3; return true; } double k = sqrt(B * B - 4 * A * C); double x4 = (2.0 * C * x3) / (-B + k); double y4 = (-B * x3 + 2.0 * A * y3) / (-B + k); x1 = x4 + (xb - xa) * sqrt(ra * ra - (x4 - xa) * (x4 - xa) - (y4 - ya) * (y4 - ya)) / d; y1 = y4 + (yb - ya) * sqrt(ra * ra - (x4 - xa) * (x4 - xa) - (y4 - ya) * (y4 - ya)) / d; x2 = x4 - (xb - xa) * sqrt(ra * ra - (x4 - xa) * (x4 - xa) - (y4 - ya) * (y4 - ya)) / d; y2 = y4 - (yb - ya) * sqrt(ra * ra - (x4 - xa) * (x4 - xa) - (y4 - ya) * (y4 - ya)) / d; return true; } int main() { double xa = 0, ya = 0, ra = 3; double xb = 6, yb = 0, rb = 2; double x1, y1, x2, y2; if (getTangentialPoints(xa, ya, ra, xb, yb, rb, x1, y1, x2, y2)) { cout << "Circle A and Circle B have tangential points:" << endl; cout << "(" << x1 << ", " << y1 << ")" << endl; cout << "(" << x2 << ", " << y2 << ")" << endl; } else { cout << "Circle A and Circle B don't have tangential points." << endl; } return 0; } ``` 其中,isEqual()函数是用来判断两个浮点数是否相等的,getTangentialPoints()函数根据上述算法实现了两圆公切线交点的计算。在主函数中,我们可以设置两个圆的圆心坐标和半径,然后调用getTangentialPoints()函数计算切点坐标
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值