Sometimes it takes a long time to make something simple. Creating wrapper subroutines makes large parametric programs cleaner and easier to read, allowing them to get larger and more useful. If you straightforwardly code each routine containing all the details it uses, you soon reach a point where the program is too complex looking to modify. Wrapper routines delegate the details of the drawing and make the flow of the calling programs easier to follow.
The ADDLINE method in Autocad VBA requires an array of 3 doubles for each endpoint of the line.
Dim lineobj as AcadLine Dim pt1(0 To 2) As Double Dim pt2(0 To 2) As Double pt1(0) = 2: pt1(1) = 3: pt1(2) = 0 pt2(0) = 40: pt2(1) = 50: pt2(2) = 0 Set lineobj = acadDoc.ModelSpace.AddLine(pt1, pt2)
By contrast the same thing can be done in autolisp with one line of code.
(command “line” (list 2 3) (list 4 5) “”)
Autocad VBA does not allow any shortcuts. Every line drawn has to use a dimensioned named assigned array of 3 doubles.
An Autocad VBA parametric drawing program would quickly require too many points to be practical. Wrapper functions are the solution. I am using the term in an informal way to indicate wrapping a VBA Autocad method to make it easier to use. Here is a simple line wrapper and how it is called.
call line(2, 3, 40, 50)
Sub line(x1 As Double, y1 As Double, x2 As Double, y2 As Double) Dim lineobj 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 lineobj = acadDoc.ModelSpace.AddLine(pt1, pt2) End Sub
Every Autocad VBA object is a candidate for one or more wrappers. The point command in autocad is not used very often in design (its very useful in the graphing calculator), but it could be easily simplified.
Sub draw_point(x1 As Double, y1 As Double, z1 As Double) Dim pointobj As AcadPoint Dim pt1(0 To 2) As Double pt1(0) = x1: pt1(1) = y1: pt1(2) = z1 Set pointobj = acadDoc.ModelSpace.AddPoint(pt1) End Sub
An array of 3 doubles is Autocad VBA’s normal way of specifying a point location used by dozens of different objects. We can make a wrapper to aid making this array. When passing arrays as arguments to a subroutine they are always passed by reference – any changes made to the array in the called program are reflected in the calling program. Unfortunately we cannot get the wrapper to dimension the array for us, but we can simplify the values assignment a little. It does help when a lot of points are being set up.
Dim pt2(0 to 2) as Double
Call initpt(pt2, 2, 4, 0)
Sub initpt(ByRef ptn() As Double, val1 As Double, val2 As Double, val3 As Double) ptn(0) = val1: ptn(1) = val2: ptn(2) = val3 End Sub
The ADDLIGHTWEIGHTPOLYLINE method requires a single array of doubles, one value for each x and y. A line with two points would require an array with 4 values.
Dim plineobj As AcadLWPolyline Dim pt(1 To 4) As Double pt(1) = 2: pt(2) = 3: pt(3) = 40: pt(4) = 50 Set plineobj = acadDoc.ModelSpace.AddLightWeightPolyline(pt)
The LightWeightPolyline method can be wrapped in a box routine. Box is drawn from lower left counterclockwise. The last segment is made with the closed property. In this case a layer is specified. It could be left out of the routine or made optional.
Call mbox(0, 0, L, W, “Hidden”)
Sub mbox(x1 As Double, y1 As Double, x2 As Double, y2 As Double, strlayer As String) Dim objent As AcadLWPolyline Dim pt(1 To 8) As Double pt(1) = x1: pt(2) = y1 pt(3) = x2: pt(4) = y1 pt(5) = x2: pt(6) = y2 pt(7) = x1: pt(8) = y2 Set objent = acadDoc.ModelSpace.AddLightWeightPolyline(pt) objent.Closed = True objent.layer = strlayer End Sub
Rectangular boxes show up a lot in any design. Any plane figure with a known number of vertexes could be hard coded as above. If you have a parametric application that often uses a notched rectangle you would use a polyline wrapper expecting 6 points. Here is how the hardcoded 6 point polyline sub is coded. You can see the 12 inputs are starting to get tedious. This 6 pointed figure has 12 inputs and the 4 pointed figure above has 4 inputs because this figure does not have to have rectangular angles, it simply draws 6 points. the box above is assumed to be square with the coordinate system.
Sub test_p6() Call connect_acad Dim L As Double, W As Double, A As Double, B As Double L = 72 W = 24 A = 12 B = 18 Call p6_box(0, 0, L - B, 0, L - B, A, L, A, L, W, 0, W) End Sub Sub p6_box(p1 As Double, p2 As Double, p3 As Double, p4 As Double, p5 As Double, p6 As Double, _ p7 As Double, p8 As Double, p9 As Double, p10 As Double, p11 As Double, p12 As Double) Dim objent As AcadLWPolyline Dim pt(1 To 12) As Double pt(1) = p1: pt(2) = p2 pt(3) = p3: pt(4) = p4 pt(5) = p5: pt(6) = p6 pt(7) = p7: pt(8) = p8 pt(9) = p9: pt(10) = p10 pt(11) = p11: pt(12) = p12 Set objent = acadDoc.ModelSpace.AddLightWeightPolyline(pt) objent.Closed = True End Sub
The straightforward method to draw complex polyline figures would initially be coded all in one sub. The array would be dimensioned then loaded with values and immediately be given to the AddPoly method. This is a closed figure with 16 points.
Dim objent As AcadLWPolyline Dim pt(1 To 32) As Double pt(1) = 1: pt(2) = 0.21875 pt(3) = 0: pt(4) = 0.21875 pt(5) = 0: pt(6) = 0 pt(7) = W - 1.25: pt(8) = 0 pt(9) = W - 1.0625: pt(10) = 0.1875 pt(11) = W: pt(12) = 0.1875 pt(13) = W: pt(14) = 0.40625 pt(15) = W - 0.875: pt(16) = 0.40625 pt(17) = W - 0.875: pt(18) = 0.34375 pt(19) = W - 0.0625: pt(20) = 0.34375 pt(21) = W - 0.0625: pt(22) = 0.25 pt(23) = W - 1.08839: pt(24) = 0.25 pt(25) = W - 1.27589: pt(26) = 0.0625 pt(27) = 0.0625: pt(28) = 0.0625 pt(29) = 0.0625: pt(30) = 0.15625 pt(31) = 1: pt(32) = 0.15625 Set objent = acadDoc.ModelSpace.AddLightWeightPolyline(pt) objent.Closed = True
A general method can be devised using a generic wrapper that tests the length of the array passed. However the poly method only accepts an array of doubles, and there is no way to conveniently construct an array of doubles except by declaring the index numbers of each value as above. The array function is easier to construct, but it only works with a variant declared. That is what we will use to construct the point list, then convert it in the wrapper, which can accept an array of any size.
Sub test_draw_array() Call connect_acad Dim W As Double W = 24 Dim pt As Variant pt = Array(1, 0.21875, 0, 0.21875, _ 0, 0, W - 1.25, 0, _ W - 1.0625, 0.1875, W, 0.1875, _ W, 0.40625, W - 0.875, 0.40625, _ W - 0.875, 0.34375, W - 0.0625, 0.34375, _ W - 0.0625, 0.25, W - 1.08839, 0.25, _ W - 1.27589, 0.0625, 0.0625, 0.0625, _ 0.0625, 0.15625, 1, 0.15625) Call draw_array(pt) End Sub Sub draw_array(pt As Variant) Dim pt2() As Double Dim objent As AcadLWPolyline Dim i As Integer Dim lower As Integer, upper As Integer lower = LBound(pt) upper = UBound(pt) ReDim pt2(lower To upper) For i = lower To upper pt2(i) = pt(i) Next i Set objent = acadDoc.ModelSpace.AddLightWeightPolyline(pt2) objent.Closed = True objent.Update End Sub