Depending on how two circles are arranged, they can have 0, 2, or 4 tangent lines. If the circles don't intersect, as on the left in Figure 1, they have 4 tangents: 2 outer tangents (blue) and 2 inner tangents (red). If the circles overlap, as shown on the right in Figure 1, they have only 2 outer tangents. If one circle contains the other, they have no tangents.
Suppose the two circles C1 and C2 have radii r1 and r2 where r2 >= r1.
To find the outer tangents, consider Figure 2. The dashed circle has the same center as C2 and radius r2 - r1. By using the example
Find the tangent lines between a point and a circle in Visual Basic .NET, you can find the tangent lines between C1's center and this dashed circle. Now move that line perpendicularly to itself distance r1 to get the outer tangent shown in Figure 2. Offset the other point/circle tangent perpendicular to itself to get the other outer tangent.
To find the inner tangents, consider Figure 3. Here the dashed circle has the same center as C1 and radius r1 + r2. By again using the example
Find the tangent lines between a point and a circle in Visual Basic .NET, you can find the tangent lines between C2's center and this dashed circle. Now move that line perpendicularly to itself distance r2 to get the inner tangent shown in Figure 3. Offset the other point/circle tangent perpendicular to itself to get the other inner tangent.
The basic idea here is somewhat tricky but if you stare long enough at the pictures, you should be able to see how it works. You might also try drawing some pictures of your own.
The FindCircleCircleTangents method shown in the following code uses this technique to find the tangents between two circles.
|
' Find the tangent points for these two circles.
' Return the number of tangents: 4, 2, or 0.
Private Function FindCircleCircleTangents( _
ByVal c1 As PointF, ByVal radius1 As Single, ByVal c2 As _
PointF, ByVal radius2 As Single, _
ByRef outer1_p1 As PointF, ByRef outer1_p2 As PointF, _
ByRef outer2_p1 As PointF, ByRef outer2_p2 As PointF, _
ByRef inner1_p1 As PointF, ByRef inner1_p2 As PointF, _
ByRef inner2_p1 As PointF, ByRef inner2_p2 As PointF) _
As Integer
' Make sure radius1 <= radius2.
If (radius1 > radius2) Then
' Call this method switching the circles.
Return FindCircleCircleTangents( _
c2, radius2, c1, radius1, _
outer1_p2, outer1_p1, _
outer2_p2, outer2_p1, _
inner1_p2, inner1_p1, _
inner2_p2, inner2_p1)
End If
' Initialize the return values in case
' some tangents are missing.
outer1_p1 = New PointF(-1, -1)
outer1_p2 = New PointF(-1, -1)
outer2_p1 = New PointF(-1, -1)
outer2_p2 = New PointF(-1, -1)
inner1_p1 = New PointF(-1, -1)
inner1_p2 = New PointF(-1, -1)
inner2_p1 = New PointF(-1, -1)
inner2_p2 = New PointF(-1, -1)
' ***************************
' * Find the outer tangents *
' ***************************
Dim radius2a As Single = radius2 - radius1
If (Not FindTangents(c2, radius2a, c1, outer1_p2, _
outer2_p2)) Then
' There are no tangents.
Return 0
End If
' Get the vector perpendicular to the
' first tangent with length radius1.
Dim v1x As Single = -(outer1_p2.Y - c1.Y)
Dim v1y As Single = outer1_p2.X - c1.X
Dim v1_length As Single = CSng(Sqrt(v1x * v1x + v1y * _
v1y))
v1x *= radius1 / v1_length
v1y *= radius1 / v1_length
' Offset the tangent vector's points.
outer1_p1 = New PointF(c1.X + v1x, c1.Y + v1y)
outer1_p2 = New PointF(outer1_p2.X + v1x, outer1_p2.Y + _
v1y)
' Get the vector perpendicular to the
' second tangent with length radius1.
Dim v2x As Single = outer2_p2.Y - c1.Y
Dim v2y As Single = -(outer2_p2.X - c1.X)
Dim v2_length As Single = CSng(Sqrt(v2x * v2x + v2y * _
v2y))
v2x *= radius1 / v2_length
v2y *= radius1 / v2_length
' Offset the tangent vector's points.
outer2_p1 = New PointF(c1.X + v2x, c1.Y + v2y)
outer2_p2 = New PointF(outer2_p2.X + v2x, outer2_p2.Y + _
v2y)
' If the circles intersect, then there are no inner
' tangents.
Dim dx As Single = c2.X - c1.X
Dim dy As Single = c2.Y - c1.Y
Dim dist As Double = Sqrt(dx * dx + dy * dy)
If (dist <= radius1 + radius2) Then Return 2
' ***************************
' * Find the inner tangents *
' ***************************
Dim radius1a As Single = radius1 + radius2
FindTangents(c1, radius1a, c2, inner1_p2, inner2_p2)
' Get the vector perpendicular to the
' first tangent with length radius2.
v1x = inner1_p2.Y - c2.Y
v1y = -(inner1_p2.X - c2.X)
v1_length = CSng(Sqrt(v1x * v1x + v1y * v1y))
v1x *= radius2 / v1_length
v1y *= radius2 / v1_length
' Offset the tangent vector's points.
inner1_p1 = New PointF(c2.X + v1x, c2.Y + v1y)
inner1_p2 = New PointF(inner1_p2.X + v1x, inner1_p2.Y + _
v1y)
' Get the vector perpendicular to the
' second tangent with length radius2.
v2x = -(inner2_p2.Y - c2.Y)
v2y = inner2_p2.X - c2.X
v2_length = CSng(Sqrt(v2x * v2x + v2y * v2y))
v2x *= radius2 / v2_length
v2y *= radius2 / v2_length
' Offset the tangent vector's points.
inner2_p1 = New PointF(c2.X + v2x, c2.Y + v2y)
inner2_p2 = New PointF(inner2_p2.X + v2x, inner2_p2.Y + _
v2y)
Return 4
End Function
|