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.
Wednesday, January 26, 2005
Welcome
Hello to new friends and old. This is my second attempt at a blog focusing on creating custom code for AutoCAD and Inventor by Autodesk. For the next little while, most articles will focus on AutoCAD, as that is what I'm currently working in. If things go well, I'll be joining the ADN later this year and then the real fun will begin. (insert evil laughter here). If you have any bits of code you're having trouble with or ideas for posts, let me know. I'll try to post something every couple of days (or more) but no guarantees.
And now a bit about me: I've been working in drafting/CAD since 1998. Like a few others here, I started out on paper and moved to CAD as quickly as possible. A few systems I've worked with over the years are AutoCAD (r9 to current), SolidWorks, Inventor, ACAD MDT, ACAD Mechanical, ACAD Electrical, ADH800 (no mouse required, don't even ask!), VisionAEL, ME10 and One Space Designer.
Despite the list above, my true love is programming... still not sure why I went for Mech. Eng. in college. I program in numerous languages (16 last time I counted) and have been customizing and extending various CAD systems for more than a decade.
I've worked in a wide range of industries including (but not limited to) automotive, beef processing, telecommunications, safe/vault manufacturing and was even an AE for an Autodesk VAR for a stint before I was enticed back into the real world to automate conveyor systems.
If anyone is interested, I am available for after-hours freelance work/training/etc.
And now a bit about me: I've been working in drafting/CAD since 1998. Like a few others here, I started out on paper and moved to CAD as quickly as possible. A few systems I've worked with over the years are AutoCAD (r9 to current), SolidWorks, Inventor, ACAD MDT, ACAD Mechanical, ACAD Electrical, ADH800 (no mouse required, don't even ask!), VisionAEL, ME10 and One Space Designer.
Despite the list above, my true love is programming... still not sure why I went for Mech. Eng. in college. I program in numerous languages (16 last time I counted) and have been customizing and extending various CAD systems for more than a decade.
I've worked in a wide range of industries including (but not limited to) automotive, beef processing, telecommunications, safe/vault manufacturing and was even an AE for an Autodesk VAR for a stint before I was enticed back into the real world to automate conveyor systems.
If anyone is interested, I am available for after-hours freelance work/training/etc.