### Thursday, January 27, 2005

## Going Off on a Tangent

Platform: AutoCAD 2004

Download: DrawInsideTangent.zip

I recently had a problem where I needed to find the inside tangent points between two circles. See the image to the right for clarity. I knew where the two centers were (X and Y) and I knew the radius of both circles...but how to find the tangents. The other problem I had was that I needed a routine that was flexible enough to handle a wide range of values, point X and point Y can vary in position and the two radii can vary. The only thing I knew for sure was that point Y was below point X.

The AutoCAD API didn't have much to help me out so I headed to the web in search of an answer. There was one very descriptive article on how to solve this problem but the solution was written in C++ and was simply too complex to be ported to VB.

In the end a co-worker pointed me down the right path (thanks Mike!). Take a look at the code below; if you have any questions after trying it out, let me know.

Public Const PI = 3.14159265358979 ' 3.1415926535897932384626433832795 or atn(1.0)*4

Public Sub DrawTangent()

Dim objLine As AcadLine

Dim objArc As AcadArc

Dim pt1(0 To 2) As Double

Dim pt2(0 To 2) As Double

Dim pt3 As Variant

Dim pt4 As Variant

Dim rad1 As Double

Dim rad2 As Double

Dim dblLength As Double

Dim dblOffset As Double

Dim dblValue As Double

Dim dblAngle As Double

Dim dblTanAngle As Double

Dim dblStartAngle As Double

' Center of first circle

pt1(0) = 0#

pt1(1) = 0#

' Center of second circle

pt2(0) = 30#

pt2(1) = -3#

' Radius of first circle

rad1 = 10#

' Radius of second circle

rad2 = 1.5

' Distance between two centers (hypotenuse of triangle)

dblLength = GetDistance(pt1, pt2)

' Add both radii (opposite length of triangle)

dblOffset = rad1 + rad2

' Length of the adjacent side of the triangle between centers

dblValue = Sqr((dblLength ^ 2) - (dblOffset ^ 2))

' Angle between hypotenuse and adjacent side

dblTanAngle = Atn(dblOffset / dblValue)

' Add hypotenuse side of triangle

Set objLine = ThisDrawing.ModelSpace.AddLine(pt1, pt2)

' Angle of hypotenuse from zero

dblStartAngle = ThisDrawing.Utility.AngleFromXAxis(pt1, pt2)

' Angle of adjacent from zero

If pt2(1) >= pt1(0) Then

dblAngle = (360# * (PI / 180#)) - Abs(dblStartAngle - dblTanAngle)

Else

dblAngle = dblStartAngle - dblTanAngle

End If

' Find end point of adjacent side

pt3 = ThisDrawing.Utility.PolarPoint(pt1, dblAngle, dblValue)

' Add adjacent side of triangle

Set objLine = ThisDrawing.ModelSpace.AddLine(pt1, pt3)

' Add opposite side of triangle

Set objLine = ThisDrawing.ModelSpace.AddLine(pt3, pt2)

' Angle from zero to first tangent

dblAngle = dblAngle + (90# * (PI / 180#))

' Start of infeed angle

pt3 = ThisDrawing.Utility.PolarPoint(pt1, dblAngle, rad1 + rad2)

' Add start arc

Set objArc = ThisDrawing.ModelSpace.AddArc(pt1, rad1 + rad2, dblAngle, 90# * (PI / 180#))

' Start of end angle

pt4 = ThisDrawing.Utility.PolarPoint(pt2, dblAngle + (180# * (PI / 180#)), rad2)

' Add end arc

Set objArc = ThisDrawing.ModelSpace.AddArc(pt2, rad2, dblAngle + (180# * (PI / 180#)), 270# * (PI / 180#))

' Add line between arcs

Set objLine = ThisDrawing.ModelSpace.AddLine(pt3, pt4)

End Sub

You'll also need the "GetDistance" function. It calculates the distance between two points in all three axis of AutoCAD space.

Public Function GetDistance(distPnt1 As Variant, distPnt2 As Variant) As Double

Dim Xval As Double

Dim Yval As Double

Dim Zval As Double

Xval = distPnt1(0) - distPnt2(0) 'Difference between x values

Yval = distPnt1(1) - distPnt2(1) 'Difference between y values

Zval = distPnt1(2) - distPnt2(2) 'Difference between z values

' Calc distance using Pythagorean Theorum

GetDistance = Sqr((Sqr((Xval ^ 2) + (Yval ^ 2)) ^ 2) + (Zval ^ 2))

End Function

Try copying both functions into VBA and run the "DrawTangent" routine you should see two arcs with a perfect tangent between them. It also draws the triangle we needed to calculate the tangent points. If you need to draw tangents in other directions, the angles will have to be modified to suit but the theory above will work for any two circles as long as they don't overlap.

Download: DrawInsideTangent.zip

I recently had a problem where I needed to find the inside tangent points between two circles. See the image to the right for clarity. I knew where the two centers were (X and Y) and I knew the radius of both circles...but how to find the tangents. The other problem I had was that I needed a routine that was flexible enough to handle a wide range of values, point X and point Y can vary in position and the two radii can vary. The only thing I knew for sure was that point Y was below point X.

The AutoCAD API didn't have much to help me out so I headed to the web in search of an answer. There was one very descriptive article on how to solve this problem but the solution was written in C++ and was simply too complex to be ported to VB.

In the end a co-worker pointed me down the right path (thanks Mike!). Take a look at the code below; if you have any questions after trying it out, let me know.

Public Const PI = 3.14159265358979 ' 3.1415926535897932384626433832795 or atn(1.0)*4

Public Sub DrawTangent()

Dim objLine As AcadLine

Dim objArc As AcadArc

Dim pt1(0 To 2) As Double

Dim pt2(0 To 2) As Double

Dim pt3 As Variant

Dim pt4 As Variant

Dim rad1 As Double

Dim rad2 As Double

Dim dblLength As Double

Dim dblOffset As Double

Dim dblValue As Double

Dim dblAngle As Double

Dim dblTanAngle As Double

Dim dblStartAngle As Double

' Center of first circle

pt1(0) = 0#

pt1(1) = 0#

' Center of second circle

pt2(0) = 30#

pt2(1) = -3#

' Radius of first circle

rad1 = 10#

' Radius of second circle

rad2 = 1.5

' Distance between two centers (hypotenuse of triangle)

dblLength = GetDistance(pt1, pt2)

' Add both radii (opposite length of triangle)

dblOffset = rad1 + rad2

' Length of the adjacent side of the triangle between centers

dblValue = Sqr((dblLength ^ 2) - (dblOffset ^ 2))

' Angle between hypotenuse and adjacent side

dblTanAngle = Atn(dblOffset / dblValue)

' Add hypotenuse side of triangle

Set objLine = ThisDrawing.ModelSpace.AddLine(pt1, pt2)

' Angle of hypotenuse from zero

dblStartAngle = ThisDrawing.Utility.AngleFromXAxis(pt1, pt2)

' Angle of adjacent from zero

If pt2(1) >= pt1(0) Then

dblAngle = (360# * (PI / 180#)) - Abs(dblStartAngle - dblTanAngle)

Else

dblAngle = dblStartAngle - dblTanAngle

End If

' Find end point of adjacent side

pt3 = ThisDrawing.Utility.PolarPoint(pt1, dblAngle, dblValue)

' Add adjacent side of triangle

Set objLine = ThisDrawing.ModelSpace.AddLine(pt1, pt3)

' Add opposite side of triangle

Set objLine = ThisDrawing.ModelSpace.AddLine(pt3, pt2)

' Angle from zero to first tangent

dblAngle = dblAngle + (90# * (PI / 180#))

' Start of infeed angle

pt3 = ThisDrawing.Utility.PolarPoint(pt1, dblAngle, rad1 + rad2)

' Add start arc

Set objArc = ThisDrawing.ModelSpace.AddArc(pt1, rad1 + rad2, dblAngle, 90# * (PI / 180#))

' Start of end angle

pt4 = ThisDrawing.Utility.PolarPoint(pt2, dblAngle + (180# * (PI / 180#)), rad2)

' Add end arc

Set objArc = ThisDrawing.ModelSpace.AddArc(pt2, rad2, dblAngle + (180# * (PI / 180#)), 270# * (PI / 180#))

' Add line between arcs

Set objLine = ThisDrawing.ModelSpace.AddLine(pt3, pt4)

End Sub

You'll also need the "GetDistance" function. It calculates the distance between two points in all three axis of AutoCAD space.

Public Function GetDistance(distPnt1 As Variant, distPnt2 As Variant) As Double

Dim Xval As Double

Dim Yval As Double

Dim Zval As Double

Xval = distPnt1(0) - distPnt2(0) 'Difference between x values

Yval = distPnt1(1) - distPnt2(1) 'Difference between y values

Zval = distPnt1(2) - distPnt2(2) 'Difference between z values

' Calc distance using Pythagorean Theorum

GetDistance = Sqr((Sqr((Xval ^ 2) + (Yval ^ 2)) ^ 2) + (Zval ^ 2))

End Function

Try copying both functions into VBA and run the "DrawTangent" routine you should see two arcs with a perfect tangent between them. It also draws the triangle we needed to calculate the tangent points. If you need to draw tangents in other directions, the angles will have to be modified to suit but the theory above will work for any two circles as long as they don't overlap.

Comments:

<< Home

Amazing- complex routine to do a simple action! Amazing, that is, that AutoCAD won't do this- I can't believe it doesn't have Tangent Snap (as in MicroStation); as a very infrequent ACAD user I can't remember. Don't assume I'm just bashing ACAD, it has some nice stuff missing from MSTN but some things are so fundamental they should be in all good software. Another example is snapping to centroid- indispensible and one reason ACAD is choice #3 for me.........

Wow, it has been a while since you used AutoCAD. AutoCAD has had a tangent snap for as long as I can remember. The problem I had was finding the tangent using VBA, not with an osnap.

I stumbled upon your article & decided to give it a try on AutoCAD 2005 without using your VBA routine. I found that it works by just drawing a line, specifying tan first, pick any point on the first circle, then specifying tan again, pick any point on the second circle; AutoCAD found the tangent points on each circle.

Kin

Kin

People, the focus of this post was to draw the tangent line

**WITH CODE**. I know I can draw the line by hand but if I am creating a block with VBA I don't have the luxury of osnaps, I have to rely on a math only answer.
Sorry, but I thought the object of using CAD was to do things in the quickest possible way and if the quickest possible way means using code by all means do so, but if it can be done without using code why bother? All the same I'll leave you to do your thing your way & I'll keep doing things my way. Again, sorry to hurt your ego!

TRY THIS:

DRAW YOUR TWO CIRCLES AND ISSUE COMMAND Line AND BEFORE YOU SPECIFY 1. POINT PICK OSNAP Tangent AND PICK 1. CIRCLE,PICK OSNAP Tangent AGAIN AND PICK 2. CIRCLE.

COOL, IS IT NOT!

DRAW YOUR TWO CIRCLES AND ISSUE COMMAND Line AND BEFORE YOU SPECIFY 1. POINT PICK OSNAP Tangent AND PICK 1. CIRCLE,PICK OSNAP Tangent AGAIN AND PICK 2. CIRCLE.

COOL, IS IT NOT!

Ok, I'm going to try this one last time as I have received lots of comments and email about this article. Bosco, I think you have the right intentions but I am not picking anything on screen. Furthermore, your method would allow for four possible solutions depending where you pick on the circles. This article was about creating an inside tangent line within a larger program, not just to draw a tangent line. My day job includes writing VBA applications for Office and AutoCAD. One of the projects included creating machine templates for a project quote (layout) drawing. Due to the number of configurations each machine could have a block library just wasn't appropriate; so I made a routine that accepted a few variables and created the top view of the machinery in question. In that top view tangent lines are required. I'm not about to ask the user to pick a couple of lines to help me build a block so I had to develop a solution using math only. Again, so I am not misunderstood: The purpose of this routine was

**NOT**to draw a tangent line in AutoCAD, it was to draw a tangent line using**CODE ONLY, WITHIN A LARGER APPLICATION**.
Pretty neat...looks like maybe OSNAP needs to be exposed somehow so that the VBA code could be more like the UI.

i understand what you did and was also looking for a CODE ONLY answer for a belt drive program im working on....i will alter the code so that it will solve for the outside tangents...the system is a drive/driven/idler program that does the drawing using an excel belt calculation spreadsheet. i dont want to even look at the drawing. there is no need since all the data was found in the workbook anyway. automation is the future guys. keep up the good work.

Post a Comment
<< Home