AddLine absolute and relative variations
Relative coordinates are conceptually the same thing as a vector. Given a start point, a line drawn to relative coordinates will be the start point plus the new vector added to it. Relative data looks the same and has the same structure as the absolute point, but the programming context differs. Our standard addline wrapper using absolute coordinates we will call Line1. Our addline wrapper using relative coordinates we will call Line2. It looks the same as Line1, but the first point is absolute, the second point is relative. The line is drawn from the first point to their sum. To get the full benefit of relative coordinates, the endpoint needs to be saved to a lastpoint type variable, I will call g_pt. This is similar to the way turtle geometry remembers its current position. We use sub Line2(abs pt, rel pt) where abs pt can be but does not have to be the current point. Both Line1 and Line2 save their endpoint as g_pt. With this system we can walk down a line of features drawing an item in sequence. To draw a line from any point to a point 5 units to the east, Line2 pt1, pt(5,0,0). To draw the next line 2 units up, Line2 g_pt, pt(0,2,0). pt(x,y,z) is a wrapper i have previously detailed.
Autocad has four basic ways of addressing the coordinate system, two for 2D and 2 for 3d. Each of these has an absolute and a relative method. The absolute mode references the origin, 0,0,0. The relative mode references the last point.
If you do not type the at sign, you are entering an absolute coordinate relative to the origin.
If you type an at sign, you are entering a coordinate relative to the starting point.
Start the line command, pick a random start point, the following options can be typed to draw different lines – All options have absolute and relative modes.
Draws a line from the startpoint to the absolute coordinate address defined by 0,0
Draws a line to the right 3 and up 1 relative from the start point.
Draws a line from the startpoint to a point 3 units from the origin and at angle 45 from the zero angle line. The zero angle line is positive x, but of course it can be changed. angle zero is to the right, the east, and angles increment counter clockwise (< 90 is to top).
Draws a line 3 units long at 45 degrees from the startpoint
These are the main methods for 2D drafting. The relative address can also be typed for the first prompt. Autocad uses the LastPoint variable, adds the relative address and uses that for the first point.
for 3D there are two more methods.
The first part of the address is the same as polar coordinates, the second part raises the line to a point with Z = 4
Draws a line with cylindrical coordinates relative from the startpoint at distance and angle, then to z dimension.
Distance and angle same as polar coordinates, then an angle from the xy plane.
For instance, if a sphere the size of earth had its origin at its center, and if England were on the positive X axis, with the z-axis through the poles, the address for Moscow would be 3985<37<55, approximately, in miles. 3985 is the earth radius in miles. Latitude and Longitude use this system, though they use North South East West rather than plus minus.
@3<45<30 would use the starting point as the relative origin.
For completeness, a user should know direct distance entry, which accepts a number for distance and uses the cursor for direction.
Now lets look at autocad VBA addline. I wont do any 3D today. Addline uses absolute points. It has no built-in relative addressing, but its easy to add. Addline has only two arguments, two points.
Dim lineobj As AcadLine
Set lineobj = acadDoc.ModelSpace.AddLine (pt1, pt2)
If these are dynamic arrays, we have all kinds of options.
Rather than embed addline in our main code, the first thing we should do is make a convenient wrapper for it. We can forget the details if we do that. Lets call the basic addline wrapper with absolute point addresses Line1
Sub line1(pt1() As Double, pt2() As Double, Optional strlayer As Variant) ' line wrapper absolute pt args with optional layer Dim lineobj As AcadLine Set lineobj = acadDoc.ModelSpace.AddLine(pt1, pt2) If Not IsMissing(strlayer) Then lineobj.Layer = strlayer End If g_pt = pt2 Set g_line = lineobj End Sub
3 things are added above the minimum. An optional layer name in the arguments list and two global variables. G_pt is a dynamic array. It becomes the VBA version of LastPoint. G_line is a global acadline. All the properties and methods of the line just created are available in the calling program (including move). These dont have to be used but they are there.
Here is our current drawing project. We want to draw a notched plate for any length of plate and any center dimension on the half-slots. We have previously derived N and R, now we want to apply those numbers.
The easiest way to approach this is with a lastpoint variable that knows the endpoint of the last line is the beginning of the next line. To take advantage of that we also need relative coordinates. Line2 expects an absolute first point and a relative second point. It adds them to find the absolute lastpoint. At the end it saves the result to g_pt.
Sub line2(pt1() As Double, pt2() As Double) 'vector method, line from pt1 startpoint at pt2 displacement Dim lineobj As AcadLine Dim pt3() As Double pt3 = pt(pt1(0) + pt2(0), pt1(1) + pt2(1), pt1(2) + pt2(2)) Set lineobj = acadDoc.ModelSpace.AddLine(pt1, pt3) g_pt = pt3 Set g_line = lineobj End Sub
In our example, the left end of the line is at 0,0. There are two horizontal lines, LineR and LineC. We need a loop. If we iterate the loop N times, there is one extra slot. So the pseudocode is
Loop n times
Line1 is sufficient for LineR and initializes g_pt as the starting point of the slot (pt function is explained in detail previously)
line1 pt0, pt(R – D / 2, 0, 0)
The sub half-slot uses g_pt as its starting point and the variables for the size of the slot. Line2 is used so that the line is drawn
from g_pt @ 0, gage
line2 g_pt, pt(0, gage, 0)
Now the arc has to be made. The VBA addarc takes four arguments, the center, radius, startangle and endangle. The arc is always drawn counterclockwise. I dont have anything fancy for it. It does not use endpoints. We have to calculate the center. The startangle is zero. The endangle is 180. We can use a degree to radian converter in the wrapper so we can feed it degrees. The startpoint actually is the point we want to save as our g_pt, so we need to calculate that. The original g_pt, the ctr and the ending g_pt are all in a line with the same y value. We just need to increment the x value. V_add is a function to add two points and return their sum. It stands for vector_add. The concept of vector addition to calculate points simplifies the code.
After we have the arc, we add the last line, the same as the first line except in the other direction. Everytime we draw anything, g_pt is updated so we can use it for our next starting point. Here is the code for the half_slot.
Sub half_slot(g_pt() As Double, gage As Double, dia As Double) Dim ptc() As Double 'first vertical line with vector method line2 g_pt, pt(0, gage, 0) 'calculate arc center with by adding vector to current point ptc = v_add(g_pt, pt(dia / 2, 0, 0)) arc1 ptc, dia / 2, 0, 180 'since arc doesnt work with points 'the starting point for the next line has to be calculated g_pt = pt(g_pt(0) + dia, gage, 0) 'second vertical line with vector method ' a variable cannot be negated with a negative sign ' have to subtract from zero line2 g_pt, pt(0, 0 - gage, 0) End Sub
Here is the sub that draws the notched edge, given L, N, C and R
Sub edge_slot(L As Double, N As Integer, C As Double, R As Double) 'G = slot Gage - distance of center from edge 'D = Dia of slot Dim G As Double, D As Double Dim i As Integer 'read in globals G = hole_gage D = hole_dia 'line R1 line1 pt0, pt(R - D / 2, 0, 0) 'half_slot prior to loop half_slot g_pt, G, D 'loop draws horiz lineC and the half-slot 'absolute coordinates in the loop are messy 'line1 g_pt, pt(R + i * C - D / 2, 0, 0) 'easier to figure the vector from the startpoint For i = 1 To N line2 g_pt, pt(C - D, 0, 0) half_slot g_pt, G, D Next i 'line R2 line1 g_pt, pt(L, 0, 0) End Sub