Quantcast
Channel: CAD-Manager.com » Code Examples
Viewing all articles
Browse latest Browse all 3

AutoLisp Examples

$
0
0

Autolisp Basics

Autolisp is the grand daddy of AutoCAD programming tools and you’d be amazed at the amount of Autolisp programming tools you can find on the Internet. Given a little knowledge you can integrate existing Autolisp routines into your own and gain tremendous power over your AutoCAD based installation.

The first thing to understand is that Autolisp has a couple of key files and a key function that perform startup operations for you. The key files are called ACAD.LSP and ACADDOC.LSP and the key function is called S::STARTUP and their operations are as summarized here:

ACAD.LSP – This file loads when AutoCAD starts up. Any programming you place within this file will be automatically loaded every time AutoCAD starts. The ACAD.LSP file is normally located in the SUPPORT subdirectory of the AutoCAD installation.

ACADDOC.LSP – This file loads every time a new drawing session is started in AutoCAD 2000, 2000i or 2002 based products. Therefore any programming you place in this file will be loaded automatically every time a drawing is opened or started. Note that while the ACAD.LSP file would load in the FIRST drawing of the AutoCAD 2000 type products only the ACADDOC.LSP file will load with subsequent drawings. Since AutoCAD R14 doesn’t support multiple drawing sessions you won’t have to worry about the ACADDOC.LSP file with R14. Like the ACAD.LSP file, ACADDOC.LSP is normally located in the SUPPORT subdirectory of the AutoCAD installation.

S::STARTUP function – This function is typically within the ACADDOC.LSP file (or ACAD.LSP file for AutoCAD R14 installations) and its sole job is to execute customized commands you need to initialize your new drawing environment. This function is the perfect place to set system variables like DIMSCALE, VIEWRES parameters, current layers, etc. The most powerful aspect of the S::STARTUP function is that it invokes automatically and it lets you control exactly how the AutoCAD environment is initialized.


Simple Examples

If you created an ACADDOC.LSP file in the SUPPORT subdirectory of your AutoCAD installation and placed the following text in it what do you think would happen?

(defun s::startup ()
(alert “Hello there!”)
(princ)
)

Well, the DEFUN statement simply DEfines a FUNction (see where the DEFUN comes from) called S::STARTUP which we already know will run every time AutoCAD starts/opens a drawing. The contents of the function are simply an ALERT box notification which will say “Hello there!” followed by a PRINC statement which is traditionally the last line of a function.

Save your new ACADDOC.LSP file checking the syntax carefully to be sure that it’s right and startup AutoCAD. Do you understand the result you get?

Let’s carry the example a bit further by trying this:

(defun s::startup ()
(setvar “textsize” 0.125)
(setvar “dimtxt” 0.125)
(princ)
)

This example sets the default text size and dimension text size to a value of 0.125 (or 1/8” if you prefer) every time a drawing opens or starts. The reason I used the decimal value is that your drawing may not always be in the architectural or fractional coordinate system and thus the decimal value is the most generic way to input a value. This example shows how the SETVAR statement can be used to set AutoCAD’s system variables and also shows how to set values using a generic coordinate system.

Let’s continue the example to a logical conclusion by saying that the TEXTSIZE value really should be 0.125 times the value of the DIMSCALE that is already set in the drawing. To complete this task we’ll need a new command called GETVAR that allows us to get variables (rather than set them) and a multiplication function (the normal * operator) within a single statement. Using a bit of imagination yields the following program:

(defun s::startup ()
(setvar “textsize” (* 0.125 (getvar “dimscale”)))
(setvar “dimtxt” 0.125)
(princ)
)

Note that the statement that sets the text size first gets the DIMSCALE value then multiplies it by 0.125 and only then sets the TEXTSIZE value. The order of the operations occurs from the inner most set of parenthesis out. Please also note there are three sets of parenthesis and that they always balance.


LSP files and functions

As you begin to write your own programs it becomes logical to keep your program code stored in files that can be edited individually. These files always have the .LSP file suffix and are typically edited in a Notepad/WordPad session or in the Visual Lisp editor (which we’ll talk about more in an upcoming issue). The location of the LSP files can be in any directory you want but the easiest way to assure the files will be located is to place them in the SUPPORT folder of your AutoCAD installation.

Within the LSP files you create you may store functions, which are simply programming routines that you can run over and over. A specific type of function, the C: function, allows you to actually add commands to AutoCAD’s vocabulary. By adding new commands, or C: functions, to AutoCAD’s command set your users simply think they have a new AutoCAD command they can use. Only you will know that they are actually using a custom AutoCAD function.

As you create your custom functions and save them as LSP files you’ll need to load in the files to be sure that the functions work. Once debugged the functions can be loaded from the ACAD.LSP file we talked about in Newsletter 61.


A Real World Example

I love keyed in shortcuts for commands like L for line, or E for erase. Some while back I wanted to create a command called FZ that would always give me a zero radius fillet command (for creating sharp corners) yet would still leave the default F fillet command at whatever value I last set it at.

Therefore the program I would write would have to do the following things:

  • remember the old fillet radius (set in the FILLETRAD system variable)
  • set the new fillet radius to zero
  • invoke the fillet command and let me select the objects
  • set the fillet radius back to it’s prior setting

The way I programmed this function looks like this:

(defun c:fz () ; line 1
(setq old_radius (getvar “filletrad”)) ; line 2
(setvar “filletrad” 0) ; line 3
(command “.fillet” pause pause) ; line 4
(setvar “filletrad” old_radius) ; line 5
) ; line 6


Example Explained

In the above example I’ve added comments at the end of each line to assign line numbers. You’ll note that each comment is preceded by a semi-colon character which means that the Autolisp interpreter will ignore everything after the semicolon. This method of commenting the program function allows you to store programming notes.

Now I’ll summarize what each line of the program is doing:

  1. Defines a command function called FZ using the DEFUN statement.
  2. Holds the default fillet radius value in a variable called OLD_RADIUS using the SETQ and GETVAR statements.
  3. Sets the fillet radius in the AutoCAD session to 0 using the SETVAR statement.
  4. Invokes the FILLET command and has PAUSE statements to wait for input from the user in the form of selecting two lines. Please note that AutoCAD commands are encased in quotation marks and that PAUSE instructions do not.
  5. Sets the fillet radius back to its old value using the OLD_RADIUS value using the SETVAR statement.
  6. A final parenthesis closes out the DEFUN statement begun in line 1.


Let’s Test It

Now you can create a file called FZ.LSP that contains the programming code from above and save it into AutoCAD’s support directory. Be very sure you’ve typed everything correctly before saving the file (or get the code from my web site which I mention at the end of the newsletter).

Now start your AutoCAD session and type the following at your command prompt:

(load “fz.lsp”)

Once the file is loaded into AutoCAD you should receive confirmation at the command line that will say C:FZ which is the name of the function.

You may now test the function by typing in FZ at the command line. Before you try the new FZ command though use the standard fillet command and set the radius to some non-zero value and fillet a couple of lines to be sure the command has been set properly. Now you should be able to fillet with normal radius values by using the normal fillet command but using FZ will always invoke a zero radius fillet.

That wasn’t so hard was it?

If you’d like you can now add the LOAD instruction line of (load “fz.lsp”) in your S::STARTUP function (mentioned earlier) and your new FZ function will load automatically upon starting AutoCAD. By loading the function from S::STARTUP you’ll take care of your users without them even knowing where the new FZ command came from.


The –Command Set

Some AutoCAD commands will require an addition of a leading “-“ character to invoke them from Autolisp commands because the command is normally manipulated via a dialog box. The layer command is a prime example of this concept that you can verify simply by typing in –LAYER at the command line. Now type in LAYER at the command line and you’ll get a very different result right?

Since AutoCAD commands pass through the Autolisp command interpreter with TYPED input you’ll need to always invoke the –LAYER command in Autolisp code like this:

(command “-layer”) instead of (command “layer”)

If you don’t believe me try it at the AutoCAD command line and see how it works. Other commands I frequently use the “-“ prefix with are –STYLE for text style manipulation and –PLOT for issuing plot commands via Autolisp. You’ll want to examine these commands simply by keying them in at the command line then making some notes about the prompts you can enter into the command line.

In almost all cases with Autolisp commands you’ll need to know how the AutoCAD commands operate and understand the sequence of how to input parameters into the command to write successful functions. If you already type in commands in AutoCAD you should be all set, if not you’ve got some exploring to do. A nice way to document the various keyed in information you use in AutoCAD is to simply copy the text out of the text history window which you access using the F2 key. Then simply use the COPY function to copy the history text into your Notepad programming session.


Errors

When you inadvertently forget parenthesis, quote marks or some other key piece of code in your LSP file you will experience a variety of problems. To see these problems demonstrated try loading in the following programming examples and see what happens.

(defun c:fz ()
(setq old_radius (getvar “filletrad))
(setvar “filletrad” 0)
(command “.fillet” pause pause)
(setvar “filletrad” old_radius)
)

The error here is a missing ” after the word FILLETRAD in the second line. You should see the Autolisp interpreter asking for a ” mark.

(defun c:fz ()
(setq old_radius (getvar “filletrad”))
(setvar “filletrad” 0)
(command “.fillet” pause pause)
(setvar “filletrad” old_radius)

The error here is a missing ) at the end of the program to close the DEFUN statement. You should see the Autolisp interpreter asking for a closing parenthesis.

(defun c:fz ()
(setq old_radius (getvar “filletrad”))
(setvar “filletrad” 0)
(command “.filllet” pause pause)
(setvar “filletrad” old_radius)
)

The error here is an extra L in the word FILLLET. You’ll notice that the function will actually run but will halt when the fillet command should run.


Input and Selection Sets

In the first two installments of our programming series I covered how to store variables, manipulate system variables and use the COMMAND statement to pass instructions to the AutoCAD editor. While these skills are key to writing basic programs you’ll find that to write truly flexible programs you’ll need to be able to:

  • Prompt your users for input values (numbers, text, points)
  • Prompt your users for sets of data (using selection set identification)
  • Filter the AutoCAD database for certain entity types
  • Work with entity points (line endpoints, circle centers, etc)

The commands we’ll be utilizing to achieve these goals are as follows:

  • GETREAL (to GET a user defined REAL number)
  • GETINT (to GET a user defined INTeger number)
  • GETSTRING (to GET a user defined STRING of text)
  • GETPOINT (to GET a user defined POINT)
  • SSGET (to GET a user defined Selection Set)
  • SSGET with the “X” option (to filter the database for objects)
  • CAR, CADR and CADDR (to break points into X, Y and Z components)

As in past installments I’ll use short pieces of programming code to illustrate the concepts and ramp up the level of complexity gradually until you can understand even complex examples.


Getting Values from the User

Getting user supplied values is straightforward in Autolisp as can be seen with these statements:

(setq var1 (getreal “\nPlease input a REAL number: “))
(setq var2 (getint “\nPlease input an INTEGER number: “))
(setq var3 (getstring “\nPlease input a piece of text: “))

Try pasting these examples into your AutoCAD command line to run the statements interactively and you’ll see immediately what’s happening. The interesting thing to note is that when using the GETINT statement that you can’t input a real number or a piece of text. You’ll also notice that a prompt is generated by the command so the user knows what information to input.

Note: The \n character is simply a line feed that assures you that the prompt to the user will be placed on a new command prompt line in the AutoCAD session!

The result of these statements will be a stored variable VAR1, VAR2 or VAR3 that can be used in other programs. Here’s a simple example of a program you can run interactively that prompts the user then makes use of the stored variable:

(setq dimtxt_height (getreal “\nDimension text height: “))
(setvar “dimtxt” dimtxt_height)

While this is a very simple example it illustrates the concept perfectly. Just acquire a value from the user then use the variable name in other commands instead of fixed values. (See examples from the previous newsletter issues if you have any questions on the SETVAR statement.)


Getting and Working with Points

While getting a point from the AutoCAD user is very simple using this form:

(setq point1 (getreal “\nPlease select a POINT location: “))

Working with the points isn’t easy because the point is actually three pieces of data that must be picked apart. Point data is really a list of X, Y and Z coordinates lumped together which can be decomposed using CAR, CADR and CADDR functions as follows:

(setq point1_x (car point1))
(setq point1_y (cadr point1))
(setq point1_z (caddr point1))

Note that an intermediate variable called POINT1 stored the point while variables POINT1_X, POINT1_Y and POINT1_Z contact the actual values for the x, y and z coordinates, respectively.

This CAR, CADR, CADDR approach requires equal components of memorization and getting used to, but you will find that you’ll grow accustomed to its usage faster than you think.


Working with Sets

Yet another component of AutoCAD programming is that AutoCAD tends to operate on sets (AutoCAD calls them selection sets) of objects. AutoCAD users provide selection sets in commands like MOVE, COPY, ROTATE, ERASE, etc. The rule of thumb is that if a command ever asks you to SELECT OBJECTS that command is making use of a selection set.

To make your programs acquire selection sets you’ll need to use the SSGET command. The most basic form of the command works like this:

(setq set1 (ssget))

or, alternately:

(setq set2 (ssget “\nPlease select objects for your set: “))

the only difference being a user prompt in the second example.

The resulting set will be stored in a variable (SET1 or SET2 in the above examples) that you can manipulate with a COMMAND style instruction. A simple program illustrates the trick:

(setq erase_set (ssget “\nPlease select objects to erase: “))
(command “.erase” erase_set “”)

This example illustrates how a selection can be obtained, stored and processed using only two lines of code!

Note: The final “” is simply an extra ENTER which you’d ordinarily have to hit manually to complete the erase command in AutoCAD.


More Sets

Lets say that you wanted to author a program that would erase all text in a drawing automatically. You will need to use the SSGET command but not for user input, rather you’ll need to filter the AutoCAD drawing for TEXT objects. The example code here looks pretty nasty but you’ll have to trust me when I tell you there isn’t a better way in standard Autolisp:

(setq text_set (ssget “x” (list (cons 0 “TEXT”))))

  • Where the “x” parameter denotes the filter
  • The “0” parameter is the entity type flag
  • The “TEXT” parameter is the entity type you’re selecting

Another example where you would select only text that is on the layer called ANNOTATIONS would look like this:

(setq text_set (ssget “x” (list (cons 0 “TEXT”) (cons 8 “ANNOTATIONS”))))

I’ll admit that this syntax isn’t very user friendly, but you will get used to it. Now simply combine one of the above statements with an ERASE command and you have a program that deletes a give entity type from the drawing automatically:

(setq text_set (ssget “x” (list (cons 0 “TEXT”))))
(command “.erase” text_set “”)

To be really thorough you may also want to trap MTEXT objects as well as TEXT objects by simply adding another SSGET function and modifying the ERASE function call like this:

(setq text_set (ssget “x” (list (cons 0 “TEXT”))))
(setq mtext_set (ssget “x” (list (cons 0 “MTEXT”))))
(command “.erase” text_set mtext_set “”)

As you can see you’ve gained a lot of power in this example using only a few lines of code. For more information on how to filter for more complex sets of objects consult the Developer’s Help section of AutoCAD’s electronic help files and search on the SSGET Autolisp function – you’ll find syntax examples a plenty there.


Viewing all articles
Browse latest Browse all 3

Latest Images

Trending Articles





Latest Images