求两圆的公切线计算

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

 

 

假设大圆半径为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

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

 

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

在C#中,两个圆的公切线通常涉及到一些几何计算,特别是当这两个圆没有交点且不相切时。这里我们可以假设我们有两个圆形,每个圆由一个中心点和半径定义。一种常见的方法是使用向量数学和欧几里得算法。 首先,我们需要获取两个圆心之间的距离(`DistanceBetweenCenters`函数),然后检查这个距离是否大于等于两个圆的半径之和或小于等于两者之差: 1. 如果距离大于半径之和,说明两个圆外离,没有公切线。 2. 如果距离等于半径之和,有两条公切线,一条垂直于它们连线,另一条平行于这条连线。 3. 如果距离小于半径之差,说明圆内切,有一条唯一的公切线,即通过两个圆心的直线。 对于实际的切线计算,你需要做以下步骤: - 确定两个圆心的向量。 - 计算这两个向量的方向向量。 - 根据情况确定切线方向:如果两个圆外离,切线分别沿着两个向量;如果是内切,只有一条切线沿向量反向;如果外切,一条沿向量,另一条垂直于向量。 - 使用点到直线的距离公式找到切点,然后连接这两个切点得到切线。 以下是一个简化版伪代码示例: ```csharp public Vector2[] FindCommonTangents(Circle circle1, Circle circle2) { Vector2 centerDifference = circle2.Center - circle1.Center; double distance = centerDifference.Length(); if (distance > circle1.Radius + circle2.Radius) return new[] { null, null }; // No common tangents (outer circles) else if (distance == circle1.Radius + circle2.Radius) { // Tangent case: two tangents Vector2 tangentDirection1 = centerDifference / distance; // Parallel to line between centers Vector2 tangentDirection2 = tangentDirection1.Perpendicular(); // Perpendicular to first tangent // Calculate intersection points for each tangent // ... return new[] { tangentPoint1, tangentPoint2 }; } else // If they're inner circles, only one common tangent { // Tangent direction is along the line connecting centers Vector2 tangentDirection = centerDifference / distance; // Calculate intersection point for single tangent // ... return new[] { tangentPoint }; } } // Helper functions Vector2.Perpendicular() 和 PointOnLine() ``` 别忘了实现 `PointOnLine()` 函数来找出给定向量上经过特定点的切线位置。这需要应用一些代数知识,比如解二次方程。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值