ThisDrawing.ModelSpace

ThisDrawing.ModelSpace is a very useful way to access the ModelSpace of your drawing through VBA or VB.NET.

When developing tools that draw entites in a drawing, we can sometimes use ThisDrawing.ModelSpace, forgetting that the tool might actually end up being used in PaperSpace. This would result in bahaviour that is not expected by the user. The ideal solution would be if there were an ActiveSpace method of the ThisDrawing object, but unfortunately this does not exist. There is a workaround however:

Function ThisSpace() As AcadBlock
    If ThisDrawing.ActiveSpace = acModelSpace Then
        Set ThisSpace = ThisDrawing.ModelSpace
    Else
        Set ThisSpace = ThisDrawing.PaperSpace
    End If
End Function

 

Use this function to return the block object of either ModelSpace or PaperSpace – whichever is actively open by the user. This solves the problem mentioned above, ensuring that you are always writing code that edits the space that is currently being worked on by the user. Use a call to this function in the place of ThisDrawing.ModelSpace.

I have many tutorials on my site for how to use your VBA code in VB.NET projects. I also explain what you need to get started with coding in VB.NET, and where to download the required software for free.

Clipping with multiple boundaries

Here’s a neat little trick that can be very useful. Have you ever wanted to clip an object, say a viewport or xref, with more than one boundary? Well there is a way to achieve the result you want, but using a single boundary.

Consider this – you want to clip an object using the outer rectangle below, but you want the inner rectangle to be a hole through the middle. Hmm this is a problem if you can only select one clipping boundary isn’t it…

rectangle within another rectangle

The solution is to make it a single boundary. Draw the outer rectangle, then just draw a line into the new location, draw that boundary, then draw on top of the line you drew to connect to the inner boundary back to the outer boundary and close the polyline:

rectangle within another rectangle boundary with gap

Here’s the same thing, but with a slight gap between the overlapping lines so that you can see what I mean:

rectangle within another rectangle boundary with gap

This works with clipping xrefs, blocks, viewports, anything that requires a clipping boundary.

I hope this little tip helps you as much as it has helped me. Also, I’d like to recommend that you subscribe below if you found this useful – I have many more tips to share!

Will

AutoCAD® 2008 scale list bug

If you’re using AutoCAD® 2008, then you may have experienced slow copy/pasting in some drawings. This is one of the symptoms of a problem known as the scale list bug. This is where the annotation scale list has for some reason accumulated a huge number of scales. There is a quick fix however – you can simply purge the scale list by using the SCALELISTEDIT command, but there’s another problem. The dialog box will not display if you have excessive scales. Preceeding the command with the minus sign (-SCALELISTEDIT) forces command line entry however, so we can bypass this problem. Select the option to reset, and hopefully this should fix the problem. This issue has a habit of spreading from drawing to drawing, so make sure you fix this is the whole set of drawings you’re experiencing problems with.

For a more permenent fix, you could try adding the following line of lisp code to either acaddoc.lsp, or acad2008doc.lsp:

(COMMAND “-scalelistedit” “R” “Y” “E”)

This will simply reset the scale list every time a drawing is opened.

Hope this helps,
Will

Ray Casting Algorithm: How to determine with VBA if a point is inside a polyline in AutoCAD

Someone recently asked about determining if a point resides within a polyline using VBA. There are a few ways to achieve this, some being more complex than others, each with their own advantages. However, there is one way that is particularly simple within the AutoCAD® environment, as we are able to use built in features such as the IntersectWith method.

The concept for finding out if a point is within a polyline is this – if we were to draw a line from the point in any direction to infinity, the number of intersections the line would have with the polyline would be an odd number. Think about it – if it was a square, it would cross the polyline once. For irregular shapes where the line crosses it many times, it firstly has to exit the shape – any re-entry to the shape must have a corresponding exit – so if the point is within the polyline, any line eminating from it to infinity must cross the boundary an odd number of times. And for the same reason, any point outside the boundary must cross the boundary an even number of times.

So, armed with this knowledge, we need a way to actually achieve this in AutoCAD®. And what better way of doing so is there than to simply draw a Ray in any direction, and find out how many intersections with the boundary there are? Well, that’s exactly what this code does:

Option Explicit

Sub main()
    Dim selPolyline As AcadLWPolyline
    Dim selPoint As AcadPoint
    Dim pnt As Variant
    Randomize 'Initialise random number generator
    ThisDrawing.Utility.GetEntity selPolyline, pnt, "Pick polyline"
    ThisDrawing.Utility.GetEntity selPoint, pnt, "Pick point"
    If isPointInPolyline(selPolyline, selPoint) Then
        ThisDrawing.Utility.Prompt "The point resides within the polyline"
        
    Else
        ThisDrawing.Utility.Prompt "The point resides outside the polyline"
    End If
End Sub

Function isPointInPolyline(pl As AcadLWPolyline, pnt As AcadPoint) As Boolean
    Dim p1 As Variant
    Dim p2 As Variant
    Dim ray As AcadRay
    Dim arr As Variant
    Dim upperbound As Long
    Dim IntersectionCount As Long
    p1 = pnt.Coordinates
    p2 = p1
    ' edit on 03/12/2010 for increased reliability
    ' horizontal ray exchanged for a ray with a random direction
    p2(0) = p2(0) + 1 - Rnd * 2 'offset x coordinate for secondary point in Ray by random amount
    p2(1) = p2(1) + 1 - Rnd * 2 'offset y coordinate for secondary point in Ray by random amount
    ' end of edit
    Set ray = thisSpace.AddRay(p1, p2)
    arr = ray.IntersectWith(pl, acExtendNone)
    upperbound = UBound(arr)
    If upperbound = -1 Then
    ' No intersections - the point must not be inside the polyline
    ' Assumes no elevation
        isPointInPolyline = False
    Else
        IntersectionCount = (upperbound + 1) / 3
        'number of elements in array is equal to the upperbound + 1 because of element zero
        'we divide by 3 to find the number of individual intersections because each has
        '3 coordinates - X, Y and Z
        
        If IntersectionCount Mod 2 = 0 Then
        'There are an even number of intersections - it cannot be inside the polyline
            isPointInPolyline = False
        Else
        'There are an odd number of intersections - it must be inside the polyline
            isPointInPolyline = True
        End If
        
    End If
    ray.Delete
End Function

Function thisSpace() As AcadBlock
    If ThisDrawing.ActiveSpace = acModelSpace Then
        Set thisSpace = ThisDrawing.ModelSpace
    Else
        Set thisSpace = ThisDrawing.PaperSpace
    End If
End Function

Do consider subscribing to my blog – I’ll always be posting code snippets like this, and always with a decent explanation. Please also feel free to leave comments.

Will

The Amazing FILLET Zero Command

So you’re drawing away, and you’ve got two lines that need to come together to form a corner, but at the moment the lines are too short or too long. Instead of extending or trimming them, it can be quite neat to use the FILLET command with a radius of 0.

For those of you that already knew this little tip but dodged it in the past because you have to mess around making sure your fillet radius was 0, you’re in luck because you don’t actually have to explicitly set the fillet radius to 0 at all. In a similar fashion to the TRIM and EXTEND commands, you can hold down the SHIFT key to modify the behaviour of this command. As you guessed, holding down the SHIFT key during the FILLET or CHAMFER commands will force a 0 radius or chamfer.

One final note, if you’re doing this with just lines, you’ll be left with what you started with – lines. However, if either one or both of the entities are in fact polylines, they will be joined to form a single polyline. If you planned to join them afterwards this can be useful to know.

The LENGTHEN Command

LENGTHEN is the older, much more specialised brother of the EXTEND command. Although EXTEND was always the more popular of two line-elongating siblings, he always felt somewhat shadowed by his more talented and feature rich, yet understated brother…

I could probably keep up this metaphor for the entire post, and whilst part of me wants to for pure comedy value, I feel it may detract from the usefulness of the post… So what I’m saying is the LENGTHEN command is very useful in specific situations, but in my experience isn’t very widely known or used.

As an example, say you’ve got a polyline that represents a wire going through a complex pulley arrangement. You know the route of the wire, you know how long the wire is supposed to be, but how on earth do you draw your polyline to an exact length through an irregular path? Yes, you could use the MEASURE command, but for me that is a bit inelegant for what we’re trying to do. The best way is to use the LENGTHEN command.

So, draw your line through the pulley arrangement, don’t worry about what the total length is for now, just make sure it follows the path you want. Now invoke the LENGTHEN command. In the LENGTHEN command there is the option to specify the total length – press T to select this option, and then enter the desired length. Then, you can select the line that represents your wire, and this will be extended or trimmed to the length you specified. Make sure you pick end of the line, or it will extend or trim from the wrong end. That’s it, thought I do quite like the irony of the LENGTHEN command potentially making the line shorter…

Finally, and as with all my posts, I’d like to suggest that you pop your email address in below. You’ll receive regular updates of what I’ve been adding to this blog, and I’m always going to be adding new content regularly. If you have any questions please do not hesitate to post comments – I will always be willing to answer questions.

Trim outside boundary with the EXTRIM command

Many thanks to Dave Murchison for finding the EXTRIM command, and sharing it with me. This command is basically an extension to the TRIM command. With this command you can select a boundary to trim back all objects to. This is great for clipping back construction lines etc back to the limits of whatever it is you’re drawing. Bear EXTRIM in mind in future as it clearly has great potential for saving a lot of time.

Will

The TRIM and EXTEND commands

I group the TRIM and EXTEND commands together because they’re basically equal and opposite. They are typically used quite commonly when drawing, but there are a few little tips for using them that can be really handy to know.

Basic Usage

Invoke the TRIM command. AutoCAD® then prompts you for a selection. A lot of people simply ignore this step and just use the default option to select all, but I tend to avoid doing this in nearly all cases. My reason for this is because you’re making AutoCAD® work harder if you select all. When you subsequently click an object to trim, AutoCAD® has to perform an intersection check with every single entity you selected, for each of the entities you selected to trim. So if you’ve got 10,000 entities in modelspace, and you selected to trim 50 lines, you’re asking AutoCAD® to perform 50 * 10,000 = 1 million comparisons. If AutoCAD® starts to hang and crashes, I wouldn’t place the blame entirely on AutoCAD…

 On the other hand, if you’d taken the time to select the entity you want to trim back to, you’re only asking AutoCAD® to perform 1 * 50 = 50 comparisons, which is drastically less than before. Get in the habit of doing this and you’ll avoid a lot of AutoCAD® hanging and possibly crashing.

What about the EXTEND command?

This is perhaps one of the most useful “quick tips” I’ve come across. I recommend that you do this right now – go into the CUI editor and remove the EXTEND command completely from your toolbars as you will never need to use it again. During the TRIM command, press and hold the SHIFT key to switch to extend m0de. That way you can tidy up all your loose ends without having to switch between the two commands.

Other Information

There also exists a LENGTHEN command, which you’d think to be very similar to the EXTEND command. You’d be right – the commands are very similar, but the LENGTHEN command has some very useful differences which make it worthy of a post of its own.

If you found this post useful, I’d like to encourage you to subscribe below. I will be posting tips like this all the time – there are so many useful tweaks that you’d never know unless someone told you. Let me tell you more!

AutoCAD® and Excel – a match made in heaven?

There are many ways to input commands into AutoCAD®. You will be familiar with the command line as the main method for driving AutoCAD®, any you will most likely know that toolbars are usually just shortcuts to commands that are in fact sent to the command line. Understanding how AutoCAD® accepts input from the command line allows us to invent our own ways of inputting data, and one of the most useful ways is to copy and paste commands directly into the command line.

Copy and paste this list of commands into the command line:

LINE 0,0 30,45
LINE 30,45 60,77.9422863405995
LINE 60,77.9422863405995 90,90
LINE 90,90 120,77.9422863405995
LINE 120,77.9422863405995 150,45
LINE 150,45 180,1.10263360941776E-14
LINE 180,1.10263360941776E-14 210,-45
LINE 210,-45 240,-77.9422863405995
LINE 240,-77.9422863405995 270,-90
LINE 270,-90 300,-77.9422863405995
LINE 300,-77.9422863405995 330,-45
LINE 330,-45 360,-2.20526721883552E-14  

You should now have a rather coarse looking sine wave which was drawn by a series of LINE commands. “What’s the point of that” you say? Well the drawing of a sine wave is just an arbitrary example of copy and pasting commands directly into the command line. Where this concept really comes into it’s own is when we use Excel to create the list that we copy. Here’s how I created the list above:

The method for creating the coordinates is unimportant – what you should focus on is the formula for creating the command:

="LINE " & E3 & "," & F3 & " " & E4 & "," & F4 & " "

Using a bit of concatenation of cells with the ‘&’ operator, we can make the content of cells represent a command in AutoCAD®, which we can then later copy and paste into AutoCAD®. Taking this further you can string a few commands together for each row of data, allowing you to achieve more complex tasks than drawing a simple line.  So if you had a few coordinates for say manhole locations, and each had an associated ID number, you could quite easily create a formula to firstly input a circle at the correct location, and then insert some text at the same location with the ID number. If you have a block, use the INSERT command in your formula instead. The possibilities are endless. I’ll never forget the time that I had to produce a tree survey based on a huge list of coordinates and other information in Excel. We’d budgeted for a fair amount of work, but with a bit of knowhow it was as easy as copy and paste.

I hope you found this tip useful, and if you did I would like to recommend you subscribe below. I’ve got loads more tips to share!

Command Aliases in AutoCAD® with acad.pgp

Thought I’d share something that I did a while back which turned out to be a really good move, though it may not be for everyone. The rationale behind this exercise is to make commonly used commands more at the fingertips of the user, and thus improve productivity.

I have set up a range of one and two letter command aliases that can be entered solely with the left hand using various combinations of the keys normally associated with touch typing with the left hand. I can now use my pointing device with one hand, and invoke up to 240 commands with the other.

This is arguably faster than clicking a toolbar icon, but this is not the only benefit. The user benefits from more screen space if they choose to remove toolbars they no longer need. More significantly, the user can interact with the PC without taking their eyes off the screen to type (or locate their right hand correctly to type), and can zoom/pan & analyse and think about the drawing WHILST entering commands.

It does come at a cost though, because you have to remember all the keybinds! To combat this, it helps to have some logic behind how they’re laid out – for instance I have my keybinds laid out as follows:

Commands beginning with A draw things, commands beginning with S modify things, commands beginning with D have to do with dimensioning/annotating, and commands beginning with F are miscellaneous. Notice that the first letter of each command resides on one of the keys your fingers should naturally rest upon when touch typing. Also, the commands are organised from left to right in order of when they would normally be used when constructing a drawing: Draw things, Modify them, Dim them up then Anything else.

Again to assist with remembering commands, I’ve tried to assign a second letter that corresponds well to the command itself. For example, AC is the CIRCLE command, AR is the RECTANG command, AS is the SPLINE command, SA is the ARRAY command, SF is the FILLET command, DR is the DIMRADIUS command, DS is the DIMSTYLE command etc… You get the idea.

Finally, commands that are very frequently used such as line, polyline, move and copy can be assigned to a single keystroke. For example, I’ve set A to LINE, S to MOVE and D to DIMLINEAR.

Having used this input method for quite a while now I can certainly say I like it. I currently have ZERO toolbars on my screen, and I can invoke any command I need from my left hand within about half a second. Once you’ve got used to it you instinctively know how to drive CAD – you can focus your energy on keeping your mind focussed on what you’re doing, and you need not be distracted by moving your mouse over to toolbars etc… It might sound trivial but keeping your eye on what you’re doing is helpful. You can snap your mouse to the right spot while you input the command.

Here’s my list of keybinds:


;GENERATED_KEYBINDS
;Anything entered beyond this point will be DELETED upon the next automatic update.
;Please input your own customisations BEFORE the GENERATED_KEYBINDS tag.
;Defined KeyBinds
AE, *ELLIPSE
AR, *RECTANG
AT, *MTEXT
ATT, *TEXT
AA, *LINE
AS, *SPLINE
AD, *HATCH
AF, *INSERT
AZ, *RAY
AX, *XLINE
AC, *CIRCLE
AV, *-VPORTS
AB, *BLOCK
SW, *OFFSET
SE, *MIRROR
SR, *ROTATE
ST, *TRIM
SY, *LENGTHEN
SA, *ARRAY
SS, *COPY
SD, *BLOCK
SF, *FILLET
SG, *CHAMFER
SZ, *PEDIT
SX, *EXPLODE
SC, *CHSPACE
SV, *STRETCH
SB, *SCALE
DQ, *QLEADER
DW, *DIMJOGLINE
DE, *DIMDIAMETER
DR, *DIMRADIUS
DT, *MLEADERALIGN
DA, *DIMANGULAR
DS, *DIMSTYLE
DD, *MLEADER
DDS, *MLEADERSTYLE
DF, *DIMALIGNED
DZ, *UNITS
DX, *MLEADEREDIT
DC, *DIMCONTINUE
Q, *QSAVE
E, *ERASE
R, *REGEN
A, *PLINE
S, *MOVE
D, *DIMLINEAR
F, *LAYER
\, *PSPACE
Z, *U
X, *XATTACH
V, *VBAMAN
FE, *PURGE
FT, *ALLON
FA, *LAYISO
FS, *LAYUNISO
FD, *LAYFRZ
FF, *MATCHPROP
FG, *LAYMRG
FC, *LAYMCUR
QQ, *SAVEAS
QW, *CLOSE
QE, *SAVEALL
QR, *CLOSEALL
QA, *QNEW
RE, *REVUP
RR, *REGENALL
RC, *REVCLOUD
K, "\\SWIN-FS-01\water\wh\CAD\CAD UTILITIES\Macros\keys3.dwg", 1,,
XX, *IMAGEATTACH
XC, *XCLIP
VR, *VBARUN
VA, *VBAIDE
C, *COPYCLIP
CA, *AI_SELALL
CX, *CUTCLIP
CC, *COPYBASE
CV, *PASTECLIP
CB, *PASTEORIG
PP, *PLOTPDF
PD, *PLOTDWF

One final thing, I’ve created a script embedded into a dwg file that automatically updates the acad.pgp file with keybinds. In the dwg are some QWERTY style keyboards so that you can visualise your keybind layout. Within this dwg file you can simply edit the text on each key to set what command it is associated with. Then, you can just save the drawing file and it will add the keybinds to the end of your acad.pgp file. Download the file here:

keybinds

To use this file, simply copy it to the same directory as your acad.pgp, open the .dwg and edit to suit.

If you found this post useful, please do subscribe below. I have many tips to share, and you’ve nothing to lose!