credit for tree programs above – https://people.eecs.berkeley.edu/~bh/pdf/v1ch10.pdf
A Turtle Geometry Class implementation in Autocad VBA
Class Modules are used in VBA to create custom objects. I am using a LINE class module to encapsulate Turtle Graphic commands in Autocad. The core idea of Turtle Graphics is that the pen is sitting on the screen at a specific location pointed in a specific direction. The command to draw a line is FORWARD and it only takes a single input DISTANCE. Its very similar to graphing with Polar Coordinates where the inputs are Distance and Angle from the Origin. All the math for the basic functionality uses simple trig.
A class module is inserted into the project in the same way as a standard module. Public variables are declared for x1 and y1. These are the current position of the pen. A public variable is declared for heading. This is the direction of the next line. A public boolean variable is declared for Pen. This will be used by subs PenUp and PenDown. x2 and y2 as the other end of the line are public variables mainly for convenience so they do not have to be declared elsewhere. The heading angle is always in degrees to the user, and converted to radians in the program. Turning the pen or turtle is done with Left and Right which take input as degree. There is a utility to keep angles between 0 and 360, rather than let them go very large or negative.
The actual drawing of lines is in a private sub and used by the public methods. Angles are degrees per autocad standard with zero to the right counterclockwise ascending.
Public methods are:
LEFT( ang )
RIGHT ( ang )
SETHEADING ( ang )
FD ( distance )
BACK ( distance )
SETPOS ( x , y )
Option Explicit Public x1 As Double Public y1 As Double Public x2 As Double Public y2 As Double Public heading As Double Public pen As Boolean Private Sub Class_Initialize() pen = True heading = 90 'traditional turtle direction End Sub Public Sub penup() pen = False End Sub Public Sub pendown() pen = True End Sub Public Sub left(ang As Double) heading = heading + ang heading = convertang(heading) End Sub Public Sub right(ang As Double) heading = heading - ang heading = convertang(heading) End Sub Public Sub setheading(ang As Double) heading = convertang(ang) End Sub Function ang2rad(ang As Double) As Double ang2rad = ang * Pi / 180 End Function Function convertang(ang As Double) 'maintaing angles between 0 < ang < 360 inclusive If ang < 0 Then Do While ang < 0 ang = ang + 360 Loop ElseIf ang > 360 Then Do While ang > 360 ang = ang - 360 Loop End If convertang = ang End Function Sub drawpt(x1 As Double, y1 As Double, x2 As Double, y2 As Double) 'internal sub to draw line Dim acadline As acadline Dim pt1(0 To 2) As Double Dim pt2(0 To 2) As Double pt1(0) = x1: pt1(1) = y1: pt1(2) = 0 pt2(0) = x2: pt2(1) = y2: pt2(2) = 0 Set acadline = acadDoc.ModelSpace.AddLine(pt1, pt2) Update End Sub 'the main logo line drawing command Public Sub fd(dist As Double) 'assumes x1 y1 and heading x2 = x1 + dist * Cos(ang2rad(heading)) y2 = y1 + dist * Sin(ang2rad(heading)) If pen Then Call drawpt(x1, y1, x2, y2) End If 'updates to new position x1 = x2 y1 = y2 End Sub Public Sub back(dist As Double) 'assumes x1 y1 and heading x2 = x1 + dist * Cos(ang2rad(heading + 180)) y2 = y1 + dist * Sin(ang2rad(heading + 180)) If pen Then Call drawpt(x1, y1, x2, y2) End If x1 = x2 y1 = y2 End Sub Public Sub setpos(x As Double, y As Double) x2 = x y2 = y If pen Then Call drawpt(x1, y1, x2, y2) End If x1 = x2 y1 = y2 End Sub Public Sub draw_polar(dist As Double, ang As Double) 'assumes x1 y1 'in case you want to increment the angle in a loop x2 = x1 + dist * Cos(ang2rad(ang)) y2 = y1 + dist * Sin(ang2rad(ang)) If pen Then Call drawpt(x1, y1, x2, y2) End If x1 = x2 y1 = y2 End Sub Public Sub draw_polar_at(x1 As Double, y1 As Double, dist As Double, ang As Double) 'in case you want full program control 'does not assume start point or angle x2 = x1 + dist * Cos(ang2rad(ang)) y2 = y1 + dist * Sin(ang2rad(ang)) If pen Then Call drawpt(x1, y1, x2, y2) End If End Sub
a few preliminary sample projects. In the code I declare a public instance of the CLine Class and use it repeatedly in all of the subs.
Option Explicit Public line As CLine Public Const Pi As Double = 3.14159265359 Sub init_cline() connect_acad Set line = New CLine End Sub Sub square(j As Double) Dim i As Integer For i = 1 To 4 line.fd j line.right 90 Next End Sub Sub squoggle() With line .fd 50 .right 70 .fd 10 .right 160 .fd 35 .right 58 End With End Sub Sub squaggle() Dim i As Integer Call init_cline For i = 1 To 20 squoggle Next End Sub Sub squiggle() With line .fd 50 .right 150 .fd 60 .right 100 .fd 30 .right 90 End With End Sub Sub squaretest() Dim i As Integer Call init_cline With line For i = 1 To 20 .pendown square 12 .penup .fd 20 .right 18 Next End With End Sub Sub face() Call init_cline With line square 100 .penup .fd 20 .right 90 .fd 25 .pendown .fd 50 .penup .back 75 .left 90 .fd 65 .right 90 .fd 20 .pendown square 15 .penup .fd 45 .pendown square 15 .penup .back 15 .right 90 .fd 20 .left 45 .pendown square 20 End With End Sub