Why AutoLISP
Why AutoLISP
Why AutoLISP
com/document/12318800/AutoLisp
https://www.tutocad.com/accessing-subentities-without-user-input-7473/
FacebookTwitterPinterestEmailPrintShare
Learning AutoLISP is radically different from learning AutoCAD. AutoLISP is a
programming language with its own commands, its own structure, and its own
syntax. However, with a knowledge of AutoLISP, AutoCAD operators can amplify
their powers with AutoCAD. AutoLISP puts new tools at your fingertips:
Mathematical calculations
Creating variables to hold values
Creating reusable functionsReading and changing AutoCAD system
variables
Accessing and changing entity properties
Accessing drawing file properties
Reading and writing ASCII files
But why AutoLISP? Why not BASIC or Pascal or a language that’s more commonly
known?
AutoLISP is based on the common LISP language, which is widely used in artificial
intelligence applications. As a subset of the LISP language, AutoLISP derives the
majority of its functions directly from the LISP language itself. AutoLISP is also a
superset of the LISP language, such that it contains commands specific to working
with AutoCAD. Thus, AutoLISP was chosen and developed to work with AutoCAD for
several reasons:
LISP excels at working with lists, which is precisely the type of information
AutoCAD manipulates.
The LISP interpreter is ideally suited to direct interaction by the designer.
LISP is among the easiest of all programming languages to learn and to
master.
Because of LISP’s simple syntax, its interpreter is small and easy to
implement.
The purpose of this class is to provide each student with a solid foundation in
AutoLISP. We will write a number of AutoLISP routines during the course. Many of
these routines will be useful building blocks for future AutoLISP work that you will
want to do. Some of these programs will simply need to be typed in; for others you
will need to create the steps yourself. Not only will we learn the commands of
AutoLISP, we will learn to begin to think in AutoLISP, to debug our programs, to
translate the solution to a problem in terms of AutoLISP, to use good techniques that
will be easily understandable to ourselves and others.
We will use AutoCAD’s built-in Visual LISP editor to write the AutoLISP code, and
will learn many of its helpful features for formatting, checking, and debugging our
routines.
Though much can be learned during class, your success with AutoLISP depends on
practicing the concepts and methods that we will discuss. Be sure that you set aside
some time each week to try out the techniques that you’ll learn in this class.
To initiate an AutoLISP expression, it must begin with either an open parenthesis “(”
or an exclamation point “!”. When AutoCAD sees an expression that begins with
either of these, it knows that what follows is not an AutoCAD expression, but
an AutoLISP expression, and it sends the expression to the AutoLISP executables to
be evaluated.
Here are several examples of AutoLISP expressions that could be typed in at the
Command line:
(setq A 5)
!A
!a
(getpoint “Enter point:”)
(command “line” PT1 PT2 PT3 “c”)
What makes AutoLISP so useful is its tight integration with AutoCAD and the
ability to easily share information between the two programs. We can even run
AutoCAD commands directly within AutoLISP, as we shall see by the end of
this chapter.
Command: (+ 18 6)
24 Expressionresults
AutoLISP expressions are evaluated from left to right. Example: Basic Math
Functions
Example: Basic Math Functions
Command: (+ 3 8 16 12 2)
41
Command: (- 60 15 12)
33
Command: (+ 3 8 (* 2 3))
17
Command: (+ 6 3)
9
Command: (+ 6
(_> 3)
9
Note that in the last example, since we did not close our initial parentheses before
hitting the <enter> key, AutoCAD returned with a different prompt “(_>” telling us
that our AutoLISP expression is not complete and requires one more closing
parenthesis.
PRACTICE
Try out the following basic calculations. Estimated time for completion: 5 minutes.
(+ 8 4)
(– 7 3)
(* 5 2)
(/ 10 5)
(+ 10 17 21)
(* 3 12 (– 17 5))
(+ 15 5 (* 6 4))
(/ (+ 6 3) (– 18 15))
AutoLISP is a math wizard. It can handle not only basic math functions but also
anything that a good scientific calculator can do.
Practice
Try out the following expressions. Estimated time for completion: 5 minutes.
(abs 3.0)
(abs -3.0)
(sqrt 9)
(sqrt 9.0)
(min -3 7 6.0 10 0)
(max -3 7 6.0 10 0)
(sin (/ PI 2))
(1+ 3) (1- 3)
Every List is Evaluated in the Same
Specific Manner – AutoCAD
Autolisp tutorial 4
04/17/2017 By TUTOCAD
FacebookTwitterPinterestEmailPrintShare
AutoLISP assumes that a list is an expression that needs to be evaluated. The function
must be the first element in a list and its arguments must immediately follow it. A
generalized AutoLISP function would look this way:
AutoLISP evaluates the expression depending on the function definition and
the explicit arguments that are designated.
Some functions have required arguments and some have both required and
optional arguments. In this book we will designate optional arguments in
brackets, [optional argument]. The brackets are not used in the actual routine.
Examples
We’ve already seen several examples of AutoLISP functions: the basic math
functions. In generalized form, they would look like this:
We need to be able to distinguish among five different data types: integers, reals,
strings, lists, and symbols. We will learn about additional data types when we discuss
AutoCAD entities and selection sets in later sections.
Atoms are anything that is not a list.
An integer is any number without an explicit decimal point. Integers are most
frequently used when counting (“Enter number of rows: ”) or when making a
selection (“1” is on, “0” is off).
Command:!12
12
Examples of Integers
12, -18, 0, 32767
Reals
A real is any number with an explicit decimal point. Reals are commonly used to
designate such things as coordinates of a point, distances between two points, angles
(although AutoLISP uses radians to measure angles), or for any other value that can
vary by fractional components.
Real numbers between -1.0 and 1.0 must have the zero placed before the
decimal point. Example: -0.125 or 0.0625.
AutoLISP commands that expect reals can accept integers. Example:(getreal
“Type in a Real Number: ”) 12
12.0
Reals may be expressed in exponential (or scientific) notation.
A real evaluates to itself.
Command: !2.79
2.79
Examples of Reals
2.32, -1.0789, 0.0, 1.2E+07
1. Which of the following are not valid integers? Why or why not?
1.0
32769
-32768
+15
2. Which of the following are not valid reals? Why or why not?
15.7698
-32768
.0769
1.2E+06
1.0
2.
(/ 12.0 5.0)
(/ 12 5)
Notice the different results in # 3 above. Since the two arguments in the first
expression are both reals, AutoLISP returns a real value as a result. However, in the
second expression, AutoLISP uses integer arithmetic and truncates (does not round)
the result to an integer value. Be careful when doing division of integer values.
Strings
A string is any alphanumeric character enclosed in double quotes. Strings are
commonly used to designate AutoCAD commands and options, filenames, directory
paths, and AutoCAD system variables. Anything in AutoCAD you would normally
type in at the keyboard must be enclosed in quotes.
Command: !”APPLE”
“APPLE”
Lists
A list is any expression enclosed in parentheses. Lists are used to designate
fundamental AutoCAD properties: 2D and 3D points and entity definitions.
Elements of a list can be integers, reals, strings, symbols, or even other lists.
We’ll soon see that every AutoLISP expression is enclosed in parentheses
and is, therefore, a list.
Symbols
Symbols are AutoLISP’s variable names.
Symbol names are not case sensitive. The symbols PT and pt are equal. For
consistency in this book we will capitalize symbol names while leaving all
other functions and arguments in lower case.
In the past, symbol names were usually kept short to reduce typing. However,
the Visual LISP text editor now has tools to speed up the input of names.
Therefore, it is a good idea to make your symbol names long enough to make
clear what information the symbol is storing. For example, instead of RN and
CN, use ROW_NUMBER and COLUMN_NUMBER.
Examples of Symbols
A
CENTER_POINT
POINT1
1. Indicate the data type that is used to express the following AutoCAD expressions in
AutoLISP:
“1”
“This is a string.
“”
””
A16
ROW NUMBER
PT15.5
FIRSTPOINT
D(5)
Self Check:
FacebookTwitterPinterestEmailPrintShare
One of the most powerful features of AutoLISP is the ability to store a variable and
then use it again later. In AutoLISP, these variables are called symbols, and they may
be assigned a value using the (setq) function.
A symbol evaluates to its value. You can see the current value of a symbol at
any time by typing an exclamation point (!) prior to the symbol name.
Command: !B
“This is text”
PRACTICE
Try the following exercises using the (setq) function. Estimated time for
completion: 5 minutes.
(setq A 5)
(setq B A)
(setq C (* A B))
(setq D (+ (* A B) C))
!A
!B
!C
!D
(setq D (+ D 15))
!D
Executing AutoCAD Commands
through AutoLISP – AutoCAD
Autolisp tutorial 7
04/17/2017 By TUTOCAD
FacebookTwitterPinterestEmailPrintShare
Rather than have an entirely new set of drawing and editing commands, AutoLISP
permits the user to tap all of AutoCAD’s existing commands from within AutoLISP
using the (command) function.
The first argument to the (command) function is always the command name. It is
followed by the command’s options input in the same order they would be typed at
the AutoCAD “Command:” prompt.
AutoCAD commands and options are typed in as strings.
DO NOT use command aliases.
You can include any AutoLISP symbol or expression that evaluates to an
appropriate value.
The null string “” is the equivalent of hitting the spacebar or <enter> key in
AutoCAD.
(command)
nil
Examples
Command: line
Specify first point: 0,0
Specify next point or [Undo]: 1,5
Specify next point or [Undo]:
Command: nil
Command: circle
Specify center point for circle or [3P/2P/Ttr (tan tan radius)]: <pick a point>
Specify radius of circle or [Diameter]: 2
Command: nil
Command: pline
Specify start point: 2,2
Current line-width is 0.0000
Specify next point or
[Arc/Close/Halfwidth/Length/Undo/Width]: w
Specify starting width <0.0000>: 0.100000000000000 Specify ending width
<0.1000>: 0.100000000000000
Specify next point or
[Arc/Close/Halfwidth/Length/Undo/Width]: 4,4
Specify next point or
[Arc/Close/Halfwidth/Length/Undo/Width]:
Command: nil
PRACTICE
Try the following statements at the Command line, first using the (setq) command
to specify several points, and then executing AutoCAD commands through
AutoLISP. Estimated time for completion: 5 minutes.
FacebookTwitterPinterestEmailPrintShare
AutoCAD’s SETVAR function, when used in conjunction with a system variable name,
will display the current value and permit the user to input a new value. In AutoLISP,
the user can read the value of any AutoCAD system variable using
the (getvar) function, and can set any non-read-only system variable using
the (setvar) function.
(getvar) reads the value of any AutoCAD system variable: (getvar variable_name)
(setvar) allows you to change the value of any non-read-only system variable:
Examples
At the beginning…
At the end…
PRACTICE
Try the following statements that use (getvar) and (setvar). Estimated time for
completion: 5 minutes.
1. Use AutoLISP to erase all objects within the extents of the current drawing.
2. Set the current settings for LTSCALE to half of the value of DIMSCALE.
3. (Extra Practice) Create a program to reset all your favorite system variables. We
will learn how to save it in the next section.
Self Check:
AutoLISP routines can become very complicated. Like any complex problem, it helps
to “divide and conquer” in order to understand the steps that will be necessary for the
solution. Considering one part at a time will help you figure out what else you need in
other parts. It also helps you make sure you have covered all the issues that may come
up.
Although AutoLISP routines can have many different structures, a typical one might
be divided into five general parts:
1. Prepare
3. Perform Calculations
5. Clean up
We have already seen step 4, using the (command) function to execute AutoCAD
commands. The next few sections will concentrate on how to get user input, prepare,
and clean up. For most of the remainder of the class we will be discussing how to
perform calculations.
Example
SAW.LSP
;;;Preparation
;;;Clean up
(redraw)
(setvar “cmdecho” CE-SAV)
(princ)
)
In a previous module we learned the function (getvar). This function “got” a system
variable stored in AutoCAD. Frequently when writing an AutoLISP routine, you’ll
want the user to provide information: the name of a layer, the endpoint of a line, the
angle of rotation, the number of rows, etc. AutoLISP provides a means of requesting
user input through the (getxxx) functions.
(getint [prompt] )
This function pauses for integer input and returns an integer value.
The [prompt] here and throughout is optional, though recommended, information
for the user. The prompt must be in string form.
(getreal [prompt] )
This function pauses for real input and returns a real value.
(getstring [ T ] [prompt] )
This function pauses for string input and returns a string value.
The optional T disables the spacebar for use as the <enter> key, allowing use of
spaces in a string. The T, which always has a value of T or non-nil, is most commonly
used as the flag, but anything that has value can be used, such as a number.
Use the T option with (getstring) when the user will type in multiple
words or numbers.
Do not use the T option when the user expects the spacebar to act
as <enter>, or when spaces are invalid (as when prompting for a
layer name in previous versions of AutoCAD).
Command: (getstring “What is your first name: ”)
What is your first name: Albert
“Albert”
This function pauses for point input and returns a point list of (x y z). The
optional point-list is used as a basepoint for the “drag” line.
will show from the first point you picked.> (2.4 5.7 0.0) actual returned value may
vary
This function pauses for point input and returns a point list of (x y z). The point-
list is not optional this time. It is used as basepoint for a “drag” rectangle similar to a
zoom window.
Command: (setq A (getpoint “First corner: “))
First corner: <pick a point>
(3.60591 7.25652 0.0) actual returned value may vary
Command: (getcorner A “Opposite corner: “)
Opposite corner: <pick a point>
(12.2542 11.1953 0.0) actual returned value may vary
(getdist [point-list] [prompt] )
This function pauses for real input and returns a real value. The user can enter a
decimal number, or a number based on the current linear unit measurement setting,
or can pick two points and the distance between those points will be returned. The
optional [point-list] is used as basepoint for “drag” line requiring user to only enter
the second point.
All inputs for points are available: pick, type in absolute or relative
coordinates, use an object snap, point filter, or tracking.
(getdist “Type in a distance or pick two points: “) Type in a distance or pick two
points: <pick point> Specify second point: <pick point>
9.125 actual returned value may vary
This function returns a real number in radians of an angle entered either by pointing
or by typing a value. The optional [point-list] lets you include a point (usually a
symbol that points back to information that gives you a point) that defines the first
point of the angle.
Writing Prompts
Write prompts so that the user will know exactly what you expect.
(getint “How many rows: ”)
Always capitalize the first character of the prompt and use a colon
and a space to finish up the string. This makes it look like other
AutoCAD prompts. Don’t capitalize all of it because it looks like you
are YELLING.
PRACTICE
5. At the Command: prompt, type the following and pick points or give numbers as
prompted:
(setq PT1 (getpoint “Enter a point: ”))
(setq PT2 (getpoint “Enter a point: ”))
(setq R1 (getreal “Enter a number: ”))
You will want to use an AutoLISP routine over and over again and not have to type it
in at the Command line every time. An AutoLISP routine can be created in any text
editor or word processor, and then saved as a file in ASCII text format.
AutoCAD itself includes a powerful text editor and debugger called Visual LISP. We
will use Visual LISP as our text editor and later learn some of its debugging features.
In this practice you will open an existing AutoLISP file and identify the different
parts. Then, you will create an AutoLISP file that will ask for four unique points and
will then construct a closed, four-sided polygon by drawing a line between each
point. Estimated time for completion: 10 minutes.
1. Start the Visual LISP Editor and open the file SAW.LSP.
4. Start a new file in the Visual LISP editor and save it to the name BOX1.LSP. Using
the (setq), (getpoint), and (command) functions, write up a routine that will
request user input of four points and construct a line through each point to create a
polygon.
2. What function will allow the user to input a real value by picking two points?
FacebookTwitterPinterestEmailPrintShare
Once an AutoLISP file is created, it must be loaded in AutoCAD with
the (load) function in order to be used.
The (load) function
(load filename)
Loads the specified LISP file, where filename is the AutoLISP file name without the
“.LSP” extension (“.LSP” can be included, but why type more than you have to?).
You can also load AutoLISP files and other programs using the Load Applications
dialog box. To open the dialog, choose Tools>Load Application from the pull-
down, or type APPLOAD at the Command line.
APPLOAD Options
Practice
Load the AutoLISP file you just created as described in the example above. If you
encounter problems, edit your file BOX1.LSP again and look for possible errors. We
will cover some typical errors in the next section. Estimated time for completion: 5
minutes.
1. In the edit window, highlight the text (from parenthesis to parenthesis) by double-
clicking in front of the opening or behind the closing parenthesis.
2. Press the Load selection button on the Tools toolbar in Visual LISP.
1.Make sure the file you want to run is the active window.
2 Press the Load active edit window button on the Tools toolbar in Visual LISP.
Notes
1. Continue using the file BOX1.LSP that you have loaded in the Visual LISP editor.
2. Highlight the first line and Load it to the console. When it switches to AutoCAD,
choose a point.
3. Highlight the last line and load it to the console. Minimize Visual LISP and you will
see that it created a new box using the first point you just picked but it remembered
the rest of the points from the last time you created the box.
4. Load the entire active edit window and follow the prompts. Notice this time that it
automatically switched you back to the Visual LISP editor once you picked the points.
Troubleshooting AutoLISP Files –
AutoCAD Autolisp tutorial 12
04/17/2017 By TUTOCAD
FacebookTwitterPinterestEmailPrintShare
Whenever you work with AutoLISP you will come across errors. Sometimes this is
nothing more than a misspelling of a function or, very often, the wrong number of
parentheses. Below are some common errors and some possible solutions.
Explanation: the (type) function
The “error: bad argument” message means that you have used the wrong data type.
Quite often the arguments will be stored in a symbol so you will not be able to see
what type of data it is. You can use the AutoLISP function (type) to find out.
(type element)
Examples
Before you load a file it is a good idea to check it. Check Edit Window and Check
Selection will tell you if you have too many or two few arguments to a known
function.
If you double-click on the error in the Build Output window it will highlight the
appropriate lines in the AutoLISP code.
Some problems will not come clear until you actually load the command. For
example, Check cannot tell if you need an integer and you passed on a string.
Use the (type) command or other debugging tools if you have this problem.
PRACTICE
In this practice we will create some problems for the BOX1.LSP file and then use
tools in Visual LISP to fix the problems. Estimated time for completion: 5 minutes.
2. Erase the closing quote mark (“ ) after one of the prompts. Notice how the color of
all the following lines change. Where does the new string end?
3. Double-click in front of the opening parenthesis of that same line. What happens?
4. Add a close quote and two close parentheses at the end of the file. Try double-
clicking at the same place again.
7. What is highlighted?
8. Fix the problem(s), check the routine again, and run it to make sure it works.
FacebookTwitterPinterestEmailPrintShare
So far we have saved a series of AutoLISP expressions in a *.LSP file. Every time we
load the *.LSP file, all expressions contained within it are executed. What would be
more useful is to be able to create new AutoLISP functions and use them as many
times as desired without loading each time. Such user-defined AutoLISP functions
are created using the (defun) function.
The rest of the information is the definition of the new function. Example
The first line uses the (defun) function to create a user-defined function
called DegreesToRadians and declares that the new function will require one
argument that will be referred to as DEGREE during the evaluation of the function.
Notes
Think of this as a massive (setq) function, storing all the expressions listed
within the expression under the symbol name <name>.
The (defun) function returns the name of the function.
The new function can now be used as all other pre-defined functions:
(function argument1 … argumentn). All expressions within the function are
then evaluated, and the function will return the value of the last expression.
If the user-defined function requires no arguments, simply provide an empty
list. (defun STUFF ( )…)
Do not use the name of a pre-defined function as your function name or the
pre-defined function will become inaccessible.
The name of the function is not case-sensitive.
PRACTICE
10 minutes.
3. Once you have created the file, load it and try several different angles.
(defun C:name ()
<expression1>
…
<expressionn>
);end defun
Notes
The function name argument must have a name that starts with “C:” .
The function must be defined with a nil argument list (empty list).
The function is invoked by typing the name at the “Command:” prompt.
Example
(defun C:BOX1 ()
(setq PT1 (getpoint “Lower left corner: ”))
(setq PT2 (getpoint “Lower right corner: ”))
(setq PT3 (getpoint “Upper right corner: ”))
(setq PT4 (getpoint “Upper left corner: ”))
(command “line” PT1 PT2 PT3 PT4 “close”)
)
As you create new functions in AutoLISP, you will need to decide whether you want to
create a command-line function or not.
Command-line function
Example
PRACTICE
Change BOX1.LSP to make it a command-line function and test it. Estimated time
for completion: 5 minutes.
(load “class”)
If a group of LISP functions are needed in virtually every drawing session, then they
can be loaded automatically each time you start AutoCAD.
Example
A sample ACADDOC.LSP file, this includes the code for DegreesToRadians and
then loads three separate LISP files, BOX1.lsp, MIDPT.lsp and TAG.lsp.
Another special file that you can create is the ACAD.MNL. This file of AutoLISP
routines loads whenever you load a menu by the name of ACAD. You can also create
additional *.MNL files for each partial menu you want to load. Just make sure the file
name is the same for both the .MNU and .MNL files.
Example
If you have a partial menu file named PLOTTING.MNU then you would create an
additional AutoLISP file call PLOTTING.MNL that would call (load) the AutoLISP
routines needed for that menu.
PRACTICE
Create an ACADDOC.LSP file in your class directory that will automatically load
the files you now have in TRANSLATION.LSP. We will add more later.
Example “cmdecho”
PRACTICE
Edit BOX1.LSP as indicated below to clean up the way it displays at the Command
line and to ensure desired operation. Estimated time for completion: 5 minutes.
(defun c:BOX1 ()
(graphscr)
(prompt “This routine will draw a box”)
(setq CE-SAV (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq PT1 (getpoint “\nLower left corner: ”))
(setq PT2 (getpoint “\nLower right corner: ”))
(setq PT3 (getpoint “\nUpper right corner: ”))
(setq PT4 (getpoint “\nUpper left corner: ”))
(command “line” PT1 PT2 PT3 PT4 “close”)
(redraw)
(setvar “cmdecho” CE-SAV)
(princ)
)
To explicitly type in a point list, a list of three real numbers, creates a problem:
AutoLISP will try to evaluate the list as a function.
When typing in an explicit point list, the (quote) function will tell AutoLISP not to
evaluate the list.
A point list can be explicitly typed in using the (quote) function or its shortcut, a
single quote in front of the list.
(quote ( list )) or ‘( list )
The (quote) function returns the list unevaluated. The (quote) function can be used
with any AutoLISP expression, not just lists.
Example
Command: (setq PT1 (quote (1.0 2.0 0.0))) or (setq PT1 ‘(1.0 2.0 0.0))
(1.0 2.0 0.0)
Command:
PRACTICE
Establish three points, PT1, PT2 and PT3, whose coordinates are(0.0 0.0 0.0), (1.0
2.0 0.0), and (6.0 3.0 0.0) respectively. Estimated time for completion: 5 minutes.
But we didn’t want an un-evaluated list (X Y Z), we wanted a list of the values of X, Y,
and Z. What if we type:
To solve our dilemma, the (list) function enables us to create a list from a series of
expressions.
The (list) function works better than (quote). While (quote) requires a single
list as an argument, (list) can have as many items as needed to add to the list.
(list expression1…expressionn)
The (list) function returns a single list whose elements are the value of each of
the expressions. We have now added the needed function to the list of
arguments.
Example
PRACTICE
Create a program that will prompt the user for coordinates for the X, Y, and Z
values of a center point for a circle. Also prompt the user for the radius of the circle.
Then create the center point using the values of X, Y, and Z as its respective
coordinates. Then draw the circle. Estimated time for completion: 10 minutes.
1. Prompt the user for the real number for X, real number for Y, and real number for
Z using the setq function and the getreal function.
2. Create and store a list of the values being stored by the symbols X, Y, and Z using
the setq function and the list function.
3. Prompt the user for the radius of the circle using the getdist function and store it
using the setq function.
Solution
(defun c:CIR ()
(setq X (getreal “\nX value for center point: “))
(setq Y (getreal “\nY value for center point: “))
(setq Z (getreal “\nZ value for center point: “))
(setq RAD (getdist “\nCircle radius: “))
(setq PT (list X Y Z))
(command “circle” PT RAD)
(redraw)
(princ)
)
There are times when you will want to create a list from other lists. For example, you
may want to get a point midway between two other points. To do this you would need
the x coordinate of one point and the y coordinate of the other, and then do a bit of
math.
Two key functions, (car) and (cdr), are the essential tools in extracting elements
from a list. The others, (cadr), (caddr) and (last) can also help you make new lists
from existing ones.
Examples
This time we will have the user specify the diagonal corners of a rectangular box.
The LISP routine will then calculate the coordinates of the other two corners and
draw a box.
(defun c:BOX1 ()
(graphscr)
(setq CE-SAV (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq PT1 (getpoint “\nEnter first corner of box: ”))
(setq PT2 (getcorner
”))
(setq X1 (car PT1))
(setq X2 (car PT2))
(setq Y1 (cadr PT1))
(setq Y2 (cadr PT2))
(setq PT3 (list X1 Y2))
(setq PT4 (list X2 Y1))
(command “pline” PT1 PT3 PT2 PT4 “close”)
(redraw)
(setvar “cmdecho” CE-SAV)
(princ)
)
Instead of setting so many variables, you could also create the following two
statements in place of the X1, X2, Y1, Y2 and the two PT3 and PT4 settings:
PRACTICE
Use Visual LISP to create a file called MIDPT.LSP which will place a circle midway
between two points. The midpoint can be derived by adding the respective X, Y, and
Z values together, then respectively dividing them by two, then combining them
together in a new point. Estimated time for completion: 10 minutes.
Solution
(defun c:MIDPT ()
(setq PT1 (getpoint “\nFirst point: “))
(setq X1 (car PT1))
(setq Y1 (cadr PT1))
(setq Z1 (caddr PT1))
(setq PT2 (getpoint “\nSecond point: “))
(setq X2 (car PT2))
(setq Y2 (cadr PT2))
(setq Z2 (caddr PT2))
(setq XMID (/ (+ X1 X2) 2))
(setq YMID (/ (+ Y1 Y2) 2))
(setq ZMID (/ (+ Z1 Z2) 2))
(setq MPT (list XMID YMID ZMID))
(setq RADIUS (getreal “\nRadius of Circle: “))
(command “Circle” MPT RADIUS)
)
PRACTICE
Use the functions listed on previous page to draw a balloon-type tag. First, get
input of two points, one for the endpoint of the leader, the second for the center of
the circle. Then determine the angle and the distance between the points. Use a
quarter of the value of the AutoCAD variable DIMSCALE as the radius of the circle
so they always plot out at 1/4” diameter. Find the other endpoint of the leader by
going the same distance as the radius at the same angle as the leader endpoint to
the center point, from the center point by using (polar). Then draw the circle and
the line. Estimated time for completion: 10 minutes.
Solution
(defun c:TAG ()
(setq CE-SAV (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq OS-SAVE (getvar “osnapcoord”))
(setvar “osnapcoord” 1)
(setq PT1 (getpoint “\nPick the leader endpoint:”))
(setq PT2 (getpoint PT1 “\nPick the tag center point:”))
(setq RADIUS (/ (getvar “dimscale”) 4.0))
(setq ANGLE1 (angle PT2 PT1))
(setq LEADERENDPT (polar PT2 ANGLE1 RADIUS))
(command “line” PT1 LEADERENDPT “”)
(command “circle” PT2 RADIUS)
(setvar “cmdecho” CE-SAV)
(setvar “osnapcoord” OS-SAVE)
(redraw)
(princ)
)
The OSNAPCOORD system variable controls the priority for keyboard entry verses
object snaps. Set this variable to 1 for AutoLISP routines so that the osnaps will not
take precedence over the point you assign through AutoLISP.
Restricting Acceptable Input Values
– AutoCAD Autolisp tutorial 19
04/18/2017 By TUTOCAD
FacebookTwitterPinterestEmailPrintShare
One of the most tedious tasks for the AutoLISP programmer is error trapping,
making sure the routine can handle all varied inputs from the user. By restricting the
acceptable input values with the (initget) function, you can control information
supplied by the user.
(initget [bits])
(initget (+ 1 2 4))
Examples
Command: (initget 1)
nil
Command: (setq DST (getdist “Enter distance: ”))
Enter distance: <enter>
Requires numeric distance or two points.
Try again: 3.2
3.2
(initget (+ 1 2 ))
nil
Command: (setq SF (getreal “Enter scale factor: ”))
Enter scale factor: <enter>
Requires numeric value.
Try again: 0
Value must be nonzero.
Try again: 2
2.0
PRACTICE
1. Write out the initget/getxxxx combination that will be appropriate for specifying
“Number of rows:”
(defun c:BOX1 ()
(graphscr)
(setq CE-SAV (getvar “cmdecho”))
(setvar “cmdecho” 0)
(initget 1)
(setq PT1 (getpoint “\nFirst corner of box: ”))
(initget 1)
(setq PT2 (getcorner PT1 “\nOpposite corner: ”))
(setq x1 (car PT1))
(setq x2 (car PT2))
(setq y1 (cadr PT1))
(setq y2 (cadr PT2))
(setq PT3 (list X1 Y2))
(setq PT4 (list X2 Y1))
(command “pline” PT1 PT3 PT2 PT4 “close”)
(redraw)
(setvar “cmdecho” CE-SAV)
(princ)
)
The keyword string is a single string that contains all acceptable keywords separated
by spaces.
By capitalizing the minimum input required for each keyword, the user only
needs to enter the capital letter to have the whole keyword returned.
Keywords work with all (getxxx) functions except (getstring).
The bit option can still be included if you want the user to input either a
keyword or a number.
(initget 1 “Pi Two-pi”)
(setq X (getreal “Enter a number or [Pi/Two-pi]: “)
To use (initget) with a group of keywords you have to ask for the keywork through
another string function, (getkword). This function limits acceptable string
responses to those in the keyword.
(getkword [prompt])
Example
PRACTICE
Modify BOX1.LSP to allow the user to draw a red, yellow, or blue box. You will need
to adjust and control the AutoCAD variable CECOLOR.
(defun c:BOX1 ()
(graphscr)
(setq CE-SAV (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq CC-SAV (getvar “cecolor”))
(initget 1 “Red Yellow Blue”)
(setq CLR (getkword “\nSelect Red/Yellow/Blue: “))
(setvar “cecolor” CLR)
(initget 1)
(setq PT1 (getpoint “\nFirst corner of box: ”))
(initget 1)
(setq PT2 (getcorner PT1 “\nOpposite corner: ”))
(setq X1 (car PT1))
(setq X2 (car PT2))
(setq Y1 (cadr PT1))
(setq Y2 (cadr PT2))
(setq PT3 (list X1 Y2))
(setq PT4 (list X2 Y1))
(command “pline” PT1 PT3 PT2 PT4 “close”)
(redraw)
(setvar “cmdecho” CE-SAV)
(setvar “cecolor” CC-SAV)
(princ)
)
FacebookTwitterPinterestEmailPrintShare
When creating AutoLISP routines, the programmer should keep in mind not only
correct syntax, but also a well-structured program that is easy to comprehend,
forgiving of mistakes, easy to debug, and easy to edit.
Formatting
You can format manually while you type. But Visual LISP includes helpful formatting
tools. They automatically insert tabs and spaces where needed to give you added
clarity and help you track parentheses. You can either Format edit
window or Format selection.
AutoLISP ignores spaces and carriage returns, so use them to make the
routine more understandable to the programmer.
Unformatted routine:
(defun C:TRIANGLE ()
(setq PT1 (getpoint “Pick a Point: “)
PT2 (getpoint “Pick another point: “)
PT3 (list (car PT1) (cadr PT2)))
(command “line” PT1 PT2 PT3 “c”))
Formatted routine:
Commenting
Comments help you and anyone else reading the file to understand the code. Use a
semi-colon in front of any line to add comments to a file. Anything on a line to the
right of a semi-colon is ignored.
At the beginning of the routine be sure to include a comment that states the
filename, what the function does, the author, the date, and the version.
You may also want to break longer functions up into stages and explain what
each stage does.
While just one semi-colon will do the job, some people prefer two or three for
visibility. Visual LISP automatically adds three semicolons in front of any
comment starting at a blank line that is not indented, two semicolons when the
new line is indented and one when tabbed over to a column location or after a
closing parenthesis.
To automatically add comments after a closing parenthesis on a separate line,
check the “Insert form-closing comment” box in the dialog
under Tools>Environment Options> Visual LISP Format Options.
To use these tools, simply select the lines you want to comment or uncomment and
press the button. Comment Block adds semicolons at the start of the selected
lines; Uncomment Block removes the semicolons.
For example, you may want to test just a portion of your routine in AutoCAD. You can
highlight the undesired portion and comment it out with the click of a button. When
you are ready to test this section as well, highlight it again and press
the Uncomment Block tool.
Commenting Example
(defun C:TRIANGLE ()
(setq PT1 (getpoint “Pick a Point: “)
PT2 (getpoint “Pick another point: “)
PT3 (list
(car PT1)
(cadr PT2) )
;end list
) ;end setq
(command “line” PT1 PT2 PT3 “c”)
) ;end defun
Naming
Use symbol names that make sense. Use a name that relates to the value
such as, PT1, ReferencePoint, SCALE_FACTOR, etc.
Visual LISP will complete a function or symbol name if you type the first few
letters and the press Ctrl + Spacebar. Repeat if you don’t come up with the
right name at first.
Symbols are not case sensitive but capitalization can help you differentiate
between symbols and functions when you are not in Visual LISP.
Remember, don’t use PI, T, or any function name such as ANGLE as a symbol
name.
Give understandable file names for your LISP routines. For example, not
DS.LSP but DATESTAMP.LSP.
Prompting
Use error control such as the (iniget) and (getkword) functions. Expect the
unexpected input. Make the routine as easy to use as possible.
Write prompts that look like AutoCAD’s. This makes a smoother interface between
your LISP routine and the main package. For example: “Choose a color: Red or
[Blue/Yellow/Green]: ” Don’t forget that AutoCAD 2000 has a new prompt style.
Another good clarity practice is to keep the track of the variables you use as symbols
and make sure you do not leave them active in AutoCAD if they will impact another
routine. This is called localizing the variables.
All variables in use in a session of AutoCAD are stored in the atom list. This
also includes all the AutoLISP function names.
A variable can be declared exclusive to a given function. These “local” variables are
declared in the same parentheses as the argument list of the (defun):
The optional arguments are the variables that you will want permanently assigned in
a drawing session. These may be symbol information that you will use in another
AutoLISP routine. Or they are the ones you must supply for the function to work.
The optional local_variables set aside the name and value of local variables. They
will not be added to the atom-list and will only be retained in memory while the
function is executing.
The (atoms-family) function returns a list of all the symbols currently defined,
called the atom list. This way you can know what symbols have been defined in the
drawing session.
The format argument specifies whether the symbols will be returned as symbols or
strings: 0 returns a list of symbols and 1 returns list of symbols converted to strings.
The optional symbol argument is used to check whether each symbol in the symbol
list exists in the current editing session. If the symbol exists, the argument returns a
symbol name; otherwise it returns nil.
;;;MATRIX.LSP
;;;C:MATRIX – A function to create a rectangular array
;;; by total row and column distance.
(defun c:MATRIX ( / ROW-NUMBER COL-NUMBER STARTPT TOTAL-ROW
TOTAL-COL ROW-DIST COL-DIST SS1)
(command “graphscr”)
(initget (+ 1 2 4)
(setq ROW-NUMBER (getint “Number of rows (—): “))
(initget (+ 1 2 4)
(setq COL-NUMBER (getint “Number of columns (|||): “))
(setq STARTPT (getpoint “Starting point: “))
(initget (+ 1 2)
(setq TOTAL-ROW (getdist STARTPT “\nTotal row distance: “))
(initget (+ 1 2)
(setq TOTAL-COL (getdist STARTPT “\nTotal column distance: “))
(setq ROW-DIST (/ TOTAL-ROW (1- ROW-NUMBER)))
(setq COL-DIST (/ TOTAL-COL (1- COL-NUMBER)))
(setq SS1 (ssget))
(command “array” SS1 “” “r” ROW-NUMBER COL-NUMBER ROW-DIST COL-
DIST) (princ)
); close defun
Open the TAG.LSP program that you have been working on. Format it using Visual
LISP, add comments, and check the symbol names and prompts.
The Simplest Looping Function
(repeat) – AutoCAD Autolisp
tutorial 22a
04/19/2017 By TUTOCAD
FacebookTwitterPinterestEmailPrintShare
Programs frequently need to perform the same series of expressions multiple times.
Rather than copy the same line a given number of times, the (repeat) function
simplifies the process.
(repeat number
… expression …
)
The number is the number of times, in integers, to repeat the enclosed expressions.
Provided you can predetermine the number of loops desired, the (repeat) function is
the simplest choice.
Example
(defun c:MCIRCLE ()
(setq NUMBER (getint “\nEnter number of circles: “))
(setq CENTER (getpoint “\nSelect center point: “))
(setq RADIUS (getdist CENTER “\nRadius of 1st circle: “))
(setq INCREMENT (getdist “\nEnter radius increment: “))
(repeat NUMBER
(command “circle” CENTER RADIUS)
(setq RADIUS (+ RADIUS INCREMENT)) )
;_ end of repeat
(princ)
) ;_ end of defun
Note: With the (repeat) function and the other branching and looping functions, it
is a good programming technique to indent all the arguments to the looping or
branching function for easier readability. Visual LISP will do this for you
automatically as you type or when you use the Format buttons.
PRACTICE
Modify the BOX1.LSP routine to include a prompt for the number of boxes to be
drawn.
Solution
(defun c:BOX1 ()
(graphscr)
(setq CE-SAV (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq CC-SAV (getvar “cecolor”))
(initget 1 “Red Yellow Blue”)
(setq CLR (getkword “\nSelect Red/Yellow/Blue: “)) (setvar “cecolor” CLR)
(initget 1)
(repeat (getint “\nEnter number of boxes: “)
(initget 1)
(setq PT1 (getpoint “\nFirst corner of box: ”))
(initget 1)
(setq PT2 (getcorner PT1 “\nOpposite corner: ”))
(setq X1 (car PT1))
(setq X2 (car PT2))
(setq Y1 (cadr PT1))
(setq Y2 (cadr PT2))
(setq PT3 (list X1 Y2))
(setq PT4 (list X2 Y1))
(command “pline” PT1 PT3 PT2 PT4 “close”)
);end repeat
(redraw)
(setvar “cmdecho” CE-SAV)
(setvar “cecolor” CC-SAV)
(princ)
)
FacebookTwitterPinterestEmailPrintShare
When we are working with a list of data, we frequently need to work with each
individual element rather than the list as a whole. For instance, if we wanted to create
a point, PT2, which is twice as far from the origin as PT1, then we will want to
increase each of its coordinates separately by a factor of 2. By use of
the (foreach) function, we are able to act on each element in a list.
Example
Command: (setq PTLST ‘((2.0 2.0 0.0) (2.0 3.0 0.0) (1.0 2.0 0.0))) ((2.0 2.0
0.0) (2.0 3.0 0.0) (1.0 2.0 0.0))
Command: (foreach PT PTLST (command “circle” PT 1.0))
PRACTICE
Modify the BOX1.LSP file to draw a 1⁄2” circle at each of the corners of each of the
boxes. Estimated time for completion: 5 minutes.
Solution
(defun c:BOX1 ()
(graphscr)
(setq CE-SAV (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq CC-SAV (getvar “cecolor”))
(initget 1 “Red Yellow Blue”)
(setq CLR (getkword “\nSelect Red/Yellow/Blue: “))
(setvar “cecolor” CLR)
(initget 1)
(repeat (getint “\nEnter number of boxes: “)
(initget 1)
(setq PT1 (getpoint “\nFirst corner of box: ”))
(initget 1)
(setq PT2 (getcorner PT1 “\nOpposite corner: ”))
(setq X1 (car PT1))
(setq X2 (car PT2))
(setq Y1 (cadr PT1))
(setq Y2 (cadr PT2))
(setq PT3 (list X1 Y2))
(setq PT4 (list X2 Y1))
(command “pline” PT1 PT3 PT2 PT4 “close”)
(foreach PT (list PT1 PT2 PT3 PT4)
(command “circle” PT 0.25)
);end foreach
);end repeat
(redraw)
(setvar “cmdecho” CE-SAV)
(setvar “cecolor” CC-SAV)
(princ)
)
The (cons) function creates a new list by adding new_first_element to the beginning
of list.
For example, if the list NLIST was set to (“Bob” “Susan” “Hussein”), then the
expression:
would return:
(“Keisha” “Bob” “Susan” “Hussein”)
(repeat 5
(setq PTLIST (cons (getpoint “Pick a point:”)
PTLIST))
)
This would prompt the user five times to pick a point, and return a list of the points
selected. Now, (foreach) can be used to process these points.
If the list argument is nil, (cons) will return a single element list consisting of
whatever is returned by the first expression.
The list will be in reverse order.
The (reverse list) function reverses the list so the numbers will be placed in
order.
Example
The empty parentheses in the (defun) function have been filled with the
names of the symbols used in the routine. This localizes the variables so that
they remain in memory only while the routine is executing.
The (itoa) function converts atoms of an integer data type to a string data
type. (Data conversion will be covered later in the course.)
A complete solution to this exercise is on your class disk as DOORNUMBER-
A.LSP.
Conditional Expressions –
AutoCAD Autolisp tutorial 22d
04/19/2017 By TUTOCAD
FacebookTwitterPinterestEmailPrintShare
Sometimes you will want a program to do different things depending on different
conditions. This is called branching. In order to create program branches, we need to
construct “test conditions.” If the test is true, then we do one result; if false, a
different result.
(setq A 5)
PT1 – as long as it holds some value
(getpoint “Enter center point: “)
(setq A B)
These expressions return the value of “T” if true, and “nil” if false. They are divided
into two types: Numerical (=,<,>, etc.) for numbers and Logical (equal to, less than,
greater than, etc.) for other expressions.
Examples
Command: (= 5 5.0)
T
Command: (/= 5 (- 7 1))
T
Command: (setq G 3.0 H 2.96)
2.96
Command: (= G H)
nil
Command: (equal G H 0.1) – are G & H equal within 0.1?
T
Command: (equal G H 0.04) – are G & H equal within 0.04?
nil
Numerical Conditions
The following conditional expressions are valid for numbers and strings:
Logical Conditions
PRACTICE
FacebookTwitterPinterestEmailPrintShare
The (repeat) function is limited to situations where the programmer (or the user)
can determine beforehand the number of loops desired. The more common looping
situation is to continue to execute a series of expressions until a certain changing
condition is met. This is exactly the use of the (while) function.
The (while) function first evaluates the expression1. As long as it is non- nil, the
remaining expressions are evaluated and it then re-evaluates the expression1. (The
assumption is that the expressions within the loop are somehow changing
the expression1.) The cycle continues until the expression1 is nil, and
the (while) function returns the most recent value of the last expressionn.
Example
This expression draws concentric circles at a center point picked by the user. It starts
with a radius of 1 and adds 0.125 to the radius of each successive circle until the value
of the radius reaches 2.25.
Example
This expression will continue to add points to the list of points as long as the user
picks or enters coordinates, then use the list of points to draw the circles.
PRACTICE
Modify the file TAG.LSP to include incremental numbers inside the circle as long as
the user selects a point for a tag. Estimated time for completion: 10 minutes.
Solution
(defun c:TAG ()
(setq CE-SAV (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq OS-SAVE (getvar “osnapcoord”))
(setvar “osnapcoord” 1)
(initget (+ 1 2 4))
(setq TAGNUMBER (getint “\nTag starting number: “))
(while (setq PT1 (getpoint “\nPick the leader endpoint or Press Enter
tofinish: ” ))
(setq PT2 (getpoint PT1 “\nPick the tag center point: “))
(setq RADIUS (/ (getvar “dimscale”) 4.0))
(setq ANGLE1 (angle PT2 PT1))
(setq LEADERENDPT (polar PT2 ANGLE1 RADIUS))
(command “line” PT1 LEADERENDPT “”
“circle” PT2 RADIUS
“text” “m” PT2(* (getvar “dimscale”) 0.25)0(itoa
TAGNUMBER)
) ;_ end of command
(setq TAGNUMBER (1+ TAGNUMBER)) )
;_ end of while
(setvar “cmdecho” CE-SAV)
(setvar “osnapcoord” OS-SAVE)
(redraw)
(princ)
) ;_ end of defun
Note: The (itoa) function converts atoms of an integer data type to a string data
type. (Data conversion will be covered later in the course.)
A complete solution to this exercise is on your class disk as TAG-B.LSP.
FacebookTwitterPinterestEmailPrintShare
Branching is a fundamental part of programming. Based on the conditional
statements from the previous topic, the (if) function creates a two-pronged branch:
“if the condition is true, then do this; otherwise, do that.” The structure of
the (if) function permits only one test. To evaluate multiple expressions, use
the (progn) function.
The (progn) function evaluates each expression in order and returns the value of the
last expression. To the (if) function, the series of expressions appears as only one.
Example
(defun c:Larger ()
(setq A (getint “\nEnter an integer: “))
(setq B (getint “\nEnter another integer: “))
(if (< A B)
(progn
(prompt “\nThe second number is larger.”)
(prompt “\nAnd the difference is “)
(prompt (itoa (- B A)))
(princ)
)
(progn
(prompt “\nThe second number is larger.”)
(prompt “\nAnd the difference is “)
(prompt (itoa (- B A)))
)
)
)
PRACTICE
Add an (if) statement to the TAG.LSP practice that will check to see if the layer
KEYNOTE exists. If it does exist then set it current and if it does not exist create it.
This requires a test expression, (tablesearch “layer” “keynote”) that we will cover
more in-depth later.
When you have completed the routine, open a new drawing based on the
PROTOMECH.DWT template and test it. Estimated time for completion: 10
minutes.
(defun c:TAG ()
(setq CE-SAVE (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq CLAYER-SAVE (getvar “clayer”))
(if (tblsearch “layer” “keynote”)
(setvar “clayer” “keynote”)
(progn (command “-layer” “n” “keynote” “c” “cyan” “keynote” “”)
(setvar “clayer” “keynote”)
) ;_ end of progn
) ;_ end of if
(setq TAGNUMBER (getint “\nTag starting number: “))
(while (setq PT1 (getpoint “\nPick the leader endpoint [Press Enter to finish]: ”
) ;_ end of getpoint
) ;_ end of setq
(setq PT2 (getpoint PT1 “\nPick the tag center point: “))
(setq RADIUS (/ (getvar “dimscale”) 4.0))
(setq ANGLE1 (angle PT2 PT1))
(setq PT3 (polar PT2 ANGLE1 RADIUS))
(command “line” PT1 PT3 “” “circle” PT2 RADIUS
“text” “m” PT2 (* (getvar “dimscale”) 0.25)0 (itoa TAGNUMBER)
) ; end of command
(setq TAGNUMBER (1+ TAGNUMBER)) )
; end of while
(setvar “cmdecho” CE-SAVE) (setvar “clayer” CLAYER-SAVE) (redraw)
(princ)
) ;_ end of defun
(cond
(test1
expression11
…
expression1n
)
(test2
expression21
…
expression2n
)
…
(testn
expressionn1
)
…
expressionnn
(T nil)
) ;end cond
Each test expression is evaluated sequentially until one is found that is non-
nil. It then evaluates those expressions that follow the test that succeeded,
returning the value of the last of these expressions.
Any number of test expressions is possible.
It is common to use T as the final test expression as an error-checking
mechanism in case all other tests fail. For example:
Example
(defun c:object ()
(initget 1 “Circle Square Rectang”)
(setq CMD (getkword “\nEnter object type Circle/Square/Rectangle: “))
(setq PT (getpoint “\nEnter a point: “))
(cond
((= CMD “Circle”) (command “circle” PT 0.5))
((= CMD “Square”) (command “pline” PT “@1<0” “@1<90” “@1<180” “c”))
((= CMD “Rectang”) (command “pline” PT “@2<0” “@1<90” “@2<180” “c”))
)
)
PRACTICE
Create an AutoLISP routine that will let the user select from a list of blocks and
insert it. Test it in the file OFFICE.dwg. Estimated time for completion: 10 minutes.
Steps to solution
Solution
(defun c:furn ()
(initget 1 “Chair Desk PC Plant”)
(setq FURN (getkword “\n Enter furniture type to insert Chair/Desk/PC/Plant: “))
(cond
((= FURN “Chair”) (command “insert” “Chair” “s” “1” pause pause))
((= FURN “Desk”) (command “insert” “Desk” “s” “1” pause pause))
((= FURN “PC”) (command “insert” “PC” “s” “1” pause pause))
((= FURN “Plant”) (command “insert” “Plant” “s” pause pause))
)
(princ)
)
FacebookTwitterPinterestEmailPrintShare
Every object in AutoCAD has specific information associated with it that is stored in a
database. This includes such information as layer, color, and linetype, as well as the
points that define its specific geometry. This is known as the entity definition list, also
called the entity association list. Since we cannot directly read the database we will
need special AutoLISP functions to access the database and tell us about the entity.
Once we have the entity name of a selected object, we can use it to obtain its entity
definition list, by way of the (entget) function.
(entget ename)
The (entget) function returns the list containing the definition data for the entity
whose name is ename. Notice from the example below that it is a list of sublists,
which is uniquely known as an association list in AutoLISP. Each of these sublists,
known as an association pair or dotted pair, begins with an integer, and has either
one other element separated by a dot (8 . “OBJECT”) or three other elements which
are all reals (10 1.0 9.0 0.0).
The initial integer of each sublist refers to a DXF Group Code which correlates
to an entity property such as entity name, layer, entity type, endpoints of a line,
etc.
The remaining elements in each sublist refer to the entity property’s unique
value for this entity, such as value of the entity name, the value of the layer,
etc.
PRACTICE
For each of the entity names that you created in the last practice, find the entity
definition list for each and assign them to the symbols “ELIST1” to “ELIST5.”
Estimated time for completion: 5 minutes.
How to interpret and manipulate an
entity definition list (association
list) – AutoCAD Autolisp tutorial
28
04/19/2017 By TUTOCAD
FacebookTwitterPinterestEmailPrintShare
To see an entity definition list is fine, but our ultimate goal is to be able to use the
values associated with certain DXF codes, and often to change the properties of an
entity. To do that, we will need to understand the unique properties of an association
list so that we can extract an object’s properties and change its definition list.
The (assoc) function searches the association list list for the key element code and
returns the complete association pair if the code exists in list. If code is not found, it
returns nil.
For example, to find the layer association pair for entity ENT1:
Isolating Data
To isolate just the data associated with a DXF code we use the (cdr) function:
As you create more programs that use the data gathered from existing entities, you
will use this series of functions quite often:
PRACTICE
Create a routine that will switch the current layer to the layer of an object the user
picks. Use the drawing RATCHET.DWG to test the routine. The solutions below are
not completely clean, so you may also want to add Command echo toggles.
Estimated time for completion: 10 minutes.
Solution
(defun C:SETLAY ()
(setq OBJECT(car (entsel “\nSelect object for new current layer: “)))
(setq LAYERNAME (cdr (assoc 8 (entget OBJECT))))
(command “-layer” “set” LAYERNAME “”)
(princ)
)
Additional Practice
Create your own (getdxf) function that can be used in the place of the three pre-
defined functions cdr, accoc, and entget. Your function will require two arguments:
the DXF code number and the Ename of the entity from which the data will be
extracted. Then rewrite SETLAY.LSP using the DXF function.
Solution
It would be an excellent idea to add the code from this program to your
ACADDOC.LSP file, so it will load automatically and be available to any of
your programs.
Solution: (setlay) with (GETDXF) code
(defun C:SETLAY ()
(setq OBJECT (car (entsel “\nSelect object whose layer will become current: “)))
(setq LAYERNAME (getdxf 8 OBJECT))
(command “-layer” “set” LAYERNAME “”)
(princ)
)
Complete solutions to these practices are on your class disk as: SETLAY-
A.LSP, GETDXF-A.LSP, and SETLAY-B.LSP.
FacebookTwitterPinterestEmailPrintShare
In the previous section we looked at methods that allows us to use DXF code data.
Now we will examine how to change DXF code data. We could just continue to call
AutoCAD’s CHANGE command using the (command) function to change the
properties of an object. But, there is an old AutoLISP adage that states, “Real
programmers don’t use the (command) function!”
First we need to create new association pairs, then substitute one association pair for
another, and finally update the object in the drawing database.
To create a new association pair we must connect the DXF code with the proper
information. To add information to a list, we use the (cons) function.
The (cons) function creates a new list by adding new_first_element to the beginning
of list.
For example, if we wanted to create a new association pair that represented the start
point of a line, where PT1 is (1.0 1.0 0.0) and 10 is the DXF code:
But, the (cons) function will create a dotted pair if the second argument is
an atom instead of a list. This is the only way to create a dotted pair.
For example, if we wanted to create a new association pair that represented the layer
WALLS:
The (cdr) function, when a dotted pair is its argument, returns the second element
as an element, not a list.
Command: (cdr (cons 8 “WALLS”))
“WALLS”
But, when a list is its argument, the (cdr) function returns the second element as a
list.
Command: (cdr (cons 10 PT1))
(1.0 1.0 0.0)
The (subst) function searches the list for old_ item. If found, it replaces every
occurrence of old_ item with new_item and returns a new list with the changes
made. If old_item is not found, (subst) returns list unchanged.
For example, if we wanted to change the layer in our entity definition list, ELIST1,
from its existing layer to WALLS:
Simply changing the entity definition list does not change the entity in the drawing. It
is also necessary to update the drawing database, using the (entmod) function, to
reflect changes made in the entity definition list.
(entmod ename)
The (entmod) function updates the drawing database for the entity whose name is
specified by the “-1” DXF code , or entity name, in ename.
Practice
Create a function, CHANGEBLOCK.LSP, that will enable you to replace one block
with another user-designated block. Estimated time for completion: 10 minutes.
Solution
(defun C:CHANGEBLOCK ()
(setq ENT (car (entsel “Select block to replace: “))
NEWBLOCKNAME (getstring “New block name: “)
)
(if (/= NEWBLOCKNAME “”)
(progn
(setq OLDELIST (entget ENT)
OLDBLOCKNAMELIST (assoc 2 OLDELIST)
NEWBLOCKNAMELIST (cons 2 NEWBLOCKNAME)
NEWELIST (subst NEWBLOCKNAMELIST OLDBLOCKNAMELIST OLDELIST)
)
(entmod NEWELIST)
)
(prompt “\nA block name was not entered.”)
)
(princ) )
Open the drawing BLOX.DWG and load the function. Use the CHANGEBLOCK
function to change the block FROWN to SMILE.
Looks like that new function will save us quite a few keystrokes! Creating functions
like this that can be used within a larger routine is called modularity. By loading
such functions into your ACADDOC.LSP file you can also make them useable by
many other functions. You are creating your own AutoLISP commands. Here are a
few more:
;;;GETNAME – returns the Entity Name (ename)
;;; of the selected entity
(defun GETNAME ( )
(car (entsel))
)
;;;GETLIST – returns the Entity List
;;;of the selected entity
(defun GETLIST ( )
(entget (car (entsel)))
)
(entmake list)
The (entmake) function creates a new entity defined by the list. The data in
the list must be association lists and must contain the minimum information required
to define the entity. Different entity types require different minimum association
lists. If the list contains insufficient information to create an entity, the function
returns nil.
Some information, such as the layer name, is optional. If that information is not
supplied in list, the default value is used.
If a layer name does not exist in the drawing, a new layer is created.
The entity type (line, arc, circle, etc.) must be listed first in list unless an entity
name is supplied. If an entity name is supplied, it must be listed first, followed
by the entity type. The entity name is ignored when the entity is created.
Examples
(defun C:MAKECIRCLE ()
(setq LAYER (getstring “Layer: “))
(setq CENTER (getpoint “Center: “))
(setq RADIUS (getdist cen “Radius: “))
(entmake (list
(cons 0 “circle”)
(cons 8 LAYER)
(cons 10 CENTER)
(cons 40 RADIUS)
)
) (princ)
)
PRACTICE
In this practice you will change the TAG routine so that it uses
the (entmake) function to create the objects in your drawing rather than
the (command) function. Estimated time for completion: 10 minutes.
1. Write up the list of association pairs needed for the line, circle, and text objects. If
you do not know the group codes needed, check the DXF Reference Guide (Entities
section) in the Help files.
Solution
(defun c:TAG ()
…
Remove (command) functions and add the following:
The DXF dotted pair code for middle justification is ( 72 . 4) . Text also needs
both 10 and 11 set when you are using a justification other than the default.
A complete solution to this exercise is on your class disk as TAG-D.LSP
FacebookTwitterPinterestEmailPrintShare
Rather than work with a single entity, it is frequently more useful to work with groups
of entities. By creating an appropriate selection set each entity within that selection
set can be changed accordingly.
Explanation: the (ssget) function
If no options are specified, (ssget) prompts the user through AutoCAD’s general
“Select objects:” prompt.
The (ssget) function returns a selection set. This is a unique data type we
haven’t discussed before. What function can we use to find the data type of
what is returned by (ssget)?
Selection sets contain main entities only (no attributes or polyline vertices).
The selected objects are highlighted only when the (ssget) function is used
without any arguments.
You can have up to 128 open selection sets at one time. If more are
attempted, AutoLISP returns nil to all (ssget) tries. To close a selection set
variable, set its value to nil.
PRACTICE
In this practice you will create a new “Move and Rotate” command by selecting
objects, moving them and then rotating them. Estimated time for completion: 10
minutes.
Steps to the solution
1. Use (ssget) to have users select the objects to move and rotate.
2. Get the basepoint, second point, and rotation angle from the user.
3. Run the MOVE and ROTATE commands using the information gathered above.
Solution
(defun C:MoveRotate ()
(setq CE-SAVE (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq SS (ssget))
(setq CP (getpoint “\nBase point: “))
(setq PT2(getpoint “\nSecond point: “))
(setq ANG (getdist “\nRotation Angle: “))
(command “move” SS “” CP PT2)
(command “rotate” SS “” PT2 ANG)
(setvar “cmdecho” CE-SAVE)
(princ)
)
In this practice you will modify the previous Move and Rotate routine to make sure
that you have selected or deselected all the desired objects. Estimated time for
completion: 10 minutes.
2. Use (ssdel) to remove any unwanted items from the selection set.
Solution
(defun C:MoveRotate ()
(setq CE-SAVE (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq SS (ssget))
(while (setq ENAME (car (entsel “\nAdd any additional items to selection
set: “)))
(ssadd ENAME SS)
)
(while (setq ENAME (car (entsel “\nRemove any unwanted items from
the selection set: “)))
(ssdel ENAME SS)
)
(setq CP (getpoint “\nBase point: “))
(setq PT2 (getpoint “\nSecond point: “))
(setq ANG (getdist “\nRotation Angle: “))
(command “move” SS “” CP PT2)
(command “rotate” SS “” PT2 ANG)
(setvar “cmdecho” CE-SAVE)
(princ)
)
The selection_set is a selection set and the position is the location of the object you
want to process within the set.
Example
In most cases you will let the code do the numbering for you. See the practice
below.
PRACTICE
In this practice you will use the AutoLISP selection set tools to update the
(changeblock) function created earlier so that users may select more than one block
at a time. Test the routine in BLOX.DWG. Estimated time for completion: 10
minutes.
Solution
(defun C:CHANGEBLOCK ()
(setq NEWBLOCKNAME (getstring “\nNew block name: “))
(if (/= NEWBLOCKNAME “”)
(progn
(setq SS (ssget))
(setq POSITION 0)
(while (setq ENAME (ssname SS POSITION))
(setq OLDELIST (entget ENAME)
OLDBLOCKNAMELIST (assoc 2 OLDELIST)
NEWBLOCKNAMELIST (cons 2 NEWBLOCKNAME)
NEWELIST (subst NEWBLOCKNAMELIST
OLDBLOCKNAMELIST
OLDELIST)
) ;_ end of setq
(entmod NEWELIST)
(setq POSITION (1+ POSITION))
) ;_ end of while
(setq SS nil)
) ;_ end of progn
(prompt “\nA block name was not entered.”)
) ;_ end of if
(princ)
) ;_ end of defun
FacebookTwitterPinterestEmailPrintShare
Besides using the standard selection set tools analogous to AutoCAD (Window,
Crossing, Previous, Last, etc.), AutoLISP provides a mechanism, through
the (ssget) filter, to select all entities within a drawing that have specific properties.
The “X” mode of the (ssget) function scans the entire drawing and creates a selection
set containing the names of all main entities that match the criteria specified in
the filter-list.
The filter-list is an association list that contains a series of entity property association
pairs, the DXF code and the corresponding answer (8 . “layer name”), that are desired
to be selected. See next page for list of available DXF codes.
Examples
An empty or absent filter-list would cause (ssget “x”) to select all entities in
the drawing.
DXF Codes
Here are some of the more commonly used DXF codes accepted by the (ssget
“X”) function:
Practice
In this practice you will create a routine that will select all the text objects in a file
and change their layer to the layer TEXT. This uses the (ssget “X”) function. Note
the similarity to the (changeblock) routine that we created earlier. Estimated
time for completion: 10 minutes.
Solution
Relational Tests
For numeric groups (integers, reals, points, and vectors) you can use relational test
operators.
This filter-list would return all the Circle entities in a drawing which have a radius
greater than or equal to 1.0 units.
Boolean Operators
Unless otherwise specified, an “equal to” test is implied for each item in a filter list.
AutoCAD allows four Boolean operators in filter lists: AND, OR, XOR, and NOT.
You can test groups of objects by creating nested Boolean expressions that are
specified in -4 groups, like the relational operators. Each Boolean expression must be
paired and balanced correctly. The number of operands that an expression can
enclose depends on the operation.
Example
This filter-list would select all circles with a radius of 1.0 and also select all lines on
layer OBJECT:
(ssget “x”
‘((-4 . “<OR”)
(-4 . “<AND”)
(0 . “CIRCLE”)
(40 . 1.0)
(-4 . “AND>”)
(-4 . “<AND”)
(0 . “LINE”)
(8 . “OBJECT”)
(-4 . “AND>”)
(-4 . “OR>”)
)
)
PRACTICE
In this practice you will change the (textlayer) routine we created in the previous
practice so that it selects both TEXT and MTEXT. Estimated time for completion: 5
minutes.
Solution
(defun C:TEXTLAYER ()
(setq CE-SAV (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq ss (ssget “x” ‘((-4 . “<OR”) (0 . “mtext”)(0 . “text”) (-4 . “OR>”))))
(setq POSITION 0)
(while (setq ENAME (ssname SS POSITION))
(setq OLDELIST (entget ENAME)
OLDLAYERNAMELIST (assoc 8 OLDELIST)
NEWLAYERNAMELIST (cons 8 “text”)
NEWELIST (subst NEWLAYERNAMELIST
OLDLAYERNAMELIST OLDELIST)
) ;_ end of setq
(entmod NEWELIST)
(setq POSITION (1+ POSITION))
) ;_ end of while
(setq SS nil)
(setvar “cmdecho” CE-SAV)
(princ)
) ;_ end of defun
FacebookTwitterPinterestEmailPrintShare
Certain information about each drawing is contained in symbol tables. Specifically,
there are tables that contain the properties of all layers, linetypes, named views, text
styles, block definitions, UCSs, and viewports within the drawing.
The (tblnext) function is used to scan an entire symbol table. For example: (tblnext
“layer”).
Each time the (tblnext) function is executed, it returns information on the next item
in the given table. If the optional argument T is set (any non-nil character will do),
the (tblnext) function starts at the beginning of the table again. The properties of
each item in the table are returned in the form of an association list.
(tblsearch) will search the table table_name for the entrysymbol and will return the
association list which defines the entry.
Example
Additional Example
You may want to use a specific layer in a routine. If the layer does not exist, your
program will crash. Therefore, you could do a table search to see if the layer exists,
make it current if it does, and if it does not, create it:
(if (tblsearch “layer” “keynote”)
(setvar “clayer” “keynote”)
(progn (command “-layer” … create the layer…)
(setvar “clayer” “keynote”)
); _end progn
): _end if
PRACTICE
Create a Bill of Materials function that gives a count and a list of all the block names
in the drawing. Test it on BLOX.DWG. Estimated time for completion: 10 minutes.
Solution
(defun c:BOM ()
(setq BLK-INFO (tblnext “BLOCK” T))
(while BLK-INFO
(setq BLK-NAME (cdr (assoc 2 BLK-INFO)))
(setq SS1 (ssget “X” (list
(cons 0 “INSERT”)
(cons 2 BLK-NAME)
)
)
)
(if SS1
(setq COUNT (sslength SS1))
(setq COUNT 0)
)
(prompt “\n”)
(prompt (itoa COUNT))
(prompt ” “)
(prompt BLK-NAME)
(setq BLK-INFO (tblnext “BLOCK”))
)
(princ)
)
Command: (layoutlist)
(“Architectural Plan” “Electrical Plan” “Lighting Plan”)
Modifying Table Entries –
AutoCAD Autolisp tutorial 37
04/20/2017 By TUTOCAD
FacebookTwitterPinterestEmailPrintShare
While you cannot modify table entries that were accessed
using (tblnext) or (tblsearch), a more powerful function, (tblobjname), is
included that makes it easier to access table entry information and, more
importantly, allows you to modify the information.
The (tblobjname) function returns an entity name for the specified table entry.
Using (entget) with the entity name returns an entity definition list that can be
modified, and the table can then be updated using (entmod).
Example
Command: (setq LAYERNAME (tblobjname “LAYER” “Walls”))
<Entity name: 19505a8>
Symbol Table entries may only be modified with (entmod) if they were
obtained using (tblobjname). They cannot be modified if they were obtained
using (tblnext) or (tblsearch).
You can create new Symbol Table entries using (entmake).
Practice
In this practice you will use (tblobjname) to obtain the entity name of a text style
so that you can modify the style. Estimated time for completion: 10 minutes.
1. Open the drawing RATCHET.DWG. Make “Title” the current text style and place
some text on your drawing.
4. Change the font of the style to “romand.shx” by typing in the following expression:
(entmod TXL2)
7. Change the color of layer “OBJECT” to color 4 using the same process
8. If you have time: Create a standard versatile program that would do this according
to the table and DXF information.
Working with String Data –
AutoCAD Autolisp tutorial 38
04/20/2017 By TUTOCAD
FacebookTwitterPinterestEmailPrintShare
To create “clean” and effective displays and prompts, we will need to manipulate
string data as shown in the functions below.
the system variable DWGNAME holds the extension as well as the name. To
remove the extension you can use (strlen) and (substr) to remove the last
four characters (the dot and three-letter extension).
PRACTICE
Add a prompt to the TAG.LSP file that will include the last number used if there is
one.
Note that we did not include the TAGNUMBER with the local variables in the
function definition. This is so we can include the last number from the previous
use as the next number in our prompt.
A complete solution to this exercise is on your class disk as TAG-E.LSP
Note that multiple control codes can be used within the same string.
The control codes must be within the double quotes.
The control codes must be lowercase.
Example
Two other functions will help you work with specialty ASCII characters.
(ascii string)
(chr integer)
PRACTICE
Open the drawing file BLOX.DWG and then edit the LISP file BOM.LSP so that there
is a title showing “Number” and “Name”, the prompts are joined together with
(strcat), and there are tabs between the information so that the returned
information is easier to read.
(defun c:BOM ()
(setq BLK-INFO (tblnext “BLOCK” T))
(prompt “\n NUMBER \t\tNAME”)
(prompt “\n——————–“)
(while BLK-INFO
(setq BLK-NM (cdr (assoc 2 BLK-INFO)))
(setq SS1 (ssget “X”
(list (cons 0 “INSERT”)
(cons 2 BLK-NM)
) ;_ end of list
) ;_ end of ssget
) ;_ end of setq
(if SS1
(setq COUNT (sslength SS1))
(setq COUNT 0) ) ;_ end of if
(prompt (strcat “\n \t” (itoa COUNT) “\t \t” BLK- NM))
(setq BLK-INFO (tblnext “BLOCK”))
) ;_ end of while
(princ)
) ;_ end of defun
FacebookTwitterPinterestEmailPrintShare
Since the (prompt) function must be a string, you will frequently need to convert
information in a different data type to a string. We have done this repeatedly with
the (itoa) function from an integer to a string. There are also functions that convert
reals and angles to strings. Of course you may also need to change strings back to
integers, reals, or angles.
Explanation
Remember, real numbers are calculated and stored using at least 14
significant digits, although only 6 are displayed to the user in AutoLISP. They
must be converted to strings to be displayed longer.
The “f” in several functions stands for “floating point,” another name for real
numbers.
The function (float) changes an integer to a real and the function (fix) truncates
rather than rounds a real to an integer.
The functions (angtos), (rtos) and (distof) can be displayed using various unit and
angle settings. For example, you may want the angles to display in degrees, minutes
and seconds or the distance to be in architectural units.
If no mode or precision argument is supplied, the current settings of AUNITS
and AUPREC are used for (angtos) and LUNITS and LUPREC for (rtos) and
LUNITS for (distof).
If you are working with English and Metric units you may also need a function that
converts a value from one unit of measurement to another.
The amount is the integer or real you want to convert. The from_unit is the existing
type of unit and the to_unit is the new unit type.
The types of units you can choose from are found in the ACAD.UNT file.
If you try to translate between two incompatible units (such as “gallons” and
“years”) the function will return nil.
If you are converting many numbers in a program you may want to convert the
number 1.0 once. Then you can use the resulting number as a scale factor.
Examples
PRACTICE
Create a command line function, STAMP, that will allow the user to place a 1⁄4” high
text string at a point in their drawing that contains the current date and time
formatted such as 12/16/1999 11:46. Use the CDATE system variable to get the
current date and time expressed as a real number. Try doing it on your own, only
look at the solution when you get stuck. Estimated time for completion: 15 minutes.
Solution
(defun c:STAMP ()
(setq PT (getpoint “\nTime stamp insertion point: “)
CD-R (getvar “cdate”)
CD-S (rtos CD-R 2 4)
YR (substr CD-S 1 4)
MO (substr CD-S 5 2)
DY (substr CD-S 7 2)
HR (substr CD-S 10 2)
MN (substr CD-S 12 2)
DT(strcatMO“/”DY“/”YR“ ”HR“:”MN)
)
(entmake (list (cons 0 “TEXT”)
(cons 1 DT)
(cons 10 PT)
(cons 40 0.25)
)
)
(princ)
)
FacebookTwitterPinterestEmailPrintShare
Another common task is processing lists so you can come up with the correct item to
prompt or convert. You should become familiar with as many list functions as
possible. These are the fundamental tools for storing, retrieving, and processing
information with AutoLISP.
PRACTICE
Create a function in a file called EVERY3.LSP that returns a list containing every
third element of LISTX using Nth and Length. Test it using the following list:
Solution
Extra Practice
Edit EVERY3.LSP and create EVERYN.LSP, a function that lets you select every nth
element. Test it on the following list:
Solution
In order to use a file you must first open it, giving it a symbol name and designating
whether it is to be read from, written to, or appended. After use, the file must be
closed.
The file_symbol is any symbol name you want to use to name the file. It is required
so that you can close the file.
The modes are defined: “w” for writing, “r” for reading, or “a” for appending to an
existing file. The mode argument must be lower case and in quotes.
The most common use of external files is to read and write string data.
Example
PRACTICE
Create a generic routine that will put a text file into an AutoCAD drawing.
Estimated time for completion: 10 minutes.
(defun C:READ ()
(setq CE-SAVE (getvar “cmdecho”))
(setvar “cmdecho” 0)
(while (= (setq FILENAME (getstring “\nFile to read: “)) “”)
(prompt “\nA file name must be entered…”)
)
(setq FILE (open FILENAME “r”))
(setq PT1 (getpoint “\nStarting Point: “))
(setq HT (getdist PT1 “\nHeight: “))
(setq SPACE (* HT 1.667))
(while (setq TEXTLINE (read-line FILE))
(command “TEXT” pt1 ht “0” TEXTLINE)
(setq PT1 (list (car PT1) (- (cadr PT1) SPACE)))
)
(close FILE)
(setvar “cmdecho” CE-SAVE)
(princ)
)
Additional Practice
Edit BOM.LSP to write the lines to a file called “dwgname.bom”. You can then use
the file to with the (read) function we created on the previous page to bring it into a
drawing.
(defun c:BOM ()
(setq BLK-INFO (tblnext “BLOCK” T))
;;;Get the drawing name and then remove the extension from it.
(setq NAME (getvar “dwgname”))
(setq NAME (substr NAME 1 (- (strlen NAME) 4)))
;;;Open the file and give it the extension .bom
(setq FILE (open (strcat NAME “.bom”) “w”))
;;;Enter information on screen
(prompt “\n NUMBER \t\tNAME”)
(prompt “\n——————–“)
(while BLK-INFO
(setq BLK-NM (cdr (assoc 2 BLK-INFO)))
(setq SS1 (ssget “X”
(list (cons 0 “INSERT”)
(cons 2 BLK-NM)
)
)
)
(if SS1
(setq COUNT (sslength SS1))
(setq COUNT 0)
)
(prompt (strcat “\n \t” (itoa COUNT) “\t \t” BLK-NM))
;;; write information to file
(write-line (strcat (itoa COUNT) ” ” BLK-NM) FILE)
(setq BLK-INFO (tblnext “BLOCK”))
)
(close FILE)
(princ) )
Another way to add information to a file is to use the (prxxx) commands with a file
name. These functions that can print not only strings but also other expressions to
the command window and send the output to a file.
#<file “test.txt”>
12
(3.0 2.0 0.0)
“\nThis is a string \twith a tab using princ”
“\nThis is a string \twith a tab using print”
“\nThis is a string \twith a tab using prin1”
nil
Shows in the file test.txt:
In our practice we will be using an object snap. The OSMODE system variable uses
the following numbers to specify the running object snaps. To include more than one
object snap mode you would add them together.
Practice
Open the drawing file POINTS.DWG. Create an AutoLISP routine that will go to the
drawing and ask the user to select points in the drawing. (Turn on the Node object
snap.) As each point is selected, write it to a file. Then, read the information from
that file and put it back in the drawing as a list of points.
If you have time, clean up the prompts so that users do not have to type in a
text height every time but can use the previous one.
A complete solution to this exercise is on your class disk as POINTS-A.LSP
This function displays the standard AutoCAD file dialog box. It returns the name of
the file selected by the user, or nil if no file was selected.
The title argument specifies the text in the title bar of the dialog.
The filename argument specifies a default filename for the dialog. This value can be
an empty string. The extension argument specifies the default file extension used to
filter the files–if a null string “”, it defaults to * (all file types). The flags argument is
the sum of specific values shown below.
Example
If your user needs to choose a color in the middle of an AutoLISP routine you can also
call up the color dialog box.
(acad_colordlg color_number)
Example
Instead of using a list of colors to choose from like we did in our box routine earlier:
Another way to make sure users know what is going on in an AutoLISP routine is to
post an alert dialog with a single OK button.
(alert string)
Practice
Open READ.LSP and save it to a file called READ-BOM.LSP. Then add the file
dialog in place of the existing prompt to name the file.
(defun C:READ ()
(setq CE-SAVE (getvar “cmdecho”))
(setvar “cmdecho” 0)
(setq FILENAME (getfiled “Bill of Materials Files” “” “bom” 4))
(setq FILE (open FILENAME “r”))
(setq PT1 (getpoint “\nStarting Point: “))
(setq HT (getdist PT1 “\nHeight: “))
(setq SPACE (* HT 1.667))
(while (setq TEXTLINE (read-line FILE))
(command “TEXT” pt1 ht “0” TEXTLINE)
(setq PT1 (list (car PT1) (- (cadr PT1) SPACE)))
)
(close FILE)
(setvar “cmdecho” CE-SAVE)
(princ)
)
The (findfile) function checks the current directory, the ACAD.EXE directory, and
the support files search path set in the OPTIONS dialog box, in that order. If a
directory path is supplied, (findfile) searches only the designated directory.
Example
Command: (findfile “acad.mnu”)
“C:\\PROGRAM FILES\\AUTOCAD 2000\\support\\acad.mnu”
Example
Throughout this class we have used these tools found in the Visual LISP editor to help
us process the code:
Parentheses matching
Color coding
Formatting
Loading partial and full functions
Checking the function in the console window
Commenting
We are now going to look at other debugging functions in the Visual LISP editor.
These are not all the tools that come with Visual LISP but will give you a good start.
The ones we will cover in this class can help you create and fix routines by using the
search functions, creating breakpoints where you can stop and start your program,
inspecting objects such as symbols, and watching the value of symbols.
Search Functions
The search functions help you find symbol and function names used in your program.
You can find words or parts of words and replace them if needed. For instance, you
could use Find and Replace if you used shortcut symbol names such as CP and later
want to replace them with more descriptive names such as CenterPoint.
To go to the next instance of the search, press the Find toolbar string button
on the Search Toolbar, go to Search> Find/Replace Next on the pull-down
menu or press F3.
If you have already searched for a string it will be available in the Toolbar
String drop-down list on the Search toolbar. This list only shows when the
toolbar is docked.
In this practice you will use Find to identify the location of one symbol and then
replace the instances of at least one other variable. Estimated time for completion: 5
minutes.
2. Find every instance of the symbol CP. Which AutoLISP functions use this symbol?
3. Find the symbol DTR. Replace each instance of this symbol with the new name
DegreestoRadians.
4. If you have time, change some of the other variable names to longer, more
descriptive ones.
5. Save the file, then load the function and test it.
To use most of the other debugging tools, you need to stop the program in the middle
of the process and then walk through it step by step. To do this, put a breakpoint in
front of the parenthesis where you want to start. Then you can use the step buttons to
proceed as needed. You can add as many breakpoints as you want in a routine.
Toggle Breakpoint
The Toggle Breakpoint command places a “stop” in your program or turns the
breakpoint off if there was one. When you run the program it will stop at the
breakpoint, return to the VLISP editor, and highlight the next expression.
When you have reached a breakpoint you can step through the rest of the program by
using the Step Into, Step Over, and Step Out functions.
Step Into
Step Into takes you to the starting parenthesis of the innermost nested expression at
the breakpoint. For example, if you set the breakpoint at the expression below, the
cursor would move to the beginning of (getpoint “\nSelect a point: “).
If you pick Step Into again it would jump to the end of the nested expression and
then out to the end of the entire phrase. After that it would go to the first parenthesis
of the next expression in the routine.
You can tell if you are at the beginning or ending parenthesis by looking at
the Step Indicator button.
The shortcut key-in for Step Into is F8.
Step Over
Step Over evaluates the entire expression including all its interior nested
expressions and then stops at the end of the expression. Press the button again to
evaluate the next expression.
Step Out
Step Out The shortcut key-in forevaluates all functions contained in the current
function. Step Out is <Ctrl> + <Shift> + F8
You can also use tools that will ignore or evaluate the expressions and move to the
next breakpoint or out of the program.
Protected Variables
Enter the break loop and press the Reset button to cancel out of the program. Then
go into your file and change the symbol name. Reload the program and try it again.
3. Use the Load active edit window button to load the file, and start the routine by
typing SAW at the AutoCAD command prompt.
4. When you have finished typing in the variables, the process will switch back to the
Visual LISP editor.
5. Press Step Into 3 times. Notice the position of the cursor in the Step Indicator
button.
Optional:
5. When the Question box comes up choose to enter the break loop and then press
the Reset button.
7. What other clue did Visual LISP give you that DISTANCE should not be used as a
symbol name?
For example, if you inspect the number 360, you will see the following window
showing the value of the integer in binary, octal, decimal, hexadecimal and character
formats.
To inspect an object
3. If there is additional information you can double-click on the object in the Inspect
window and it will bring up the next Inspect window.
4. Or… You can start Inspect without anything highlighted and pick from the Inspect
dialog box or type in the object name.
Notes
If you select an AutoLISP expression, Inspect will process the function and
return the final value. For example,
(setq YCEN (cadr CP))
will show a real number in the Inspect window as long as CP was a point list.
You can have any number of inspect windows open at one time.
In this practice you will inspect the values of objects in an AutoLISP file and then
select an AutoCAD object and inspect its value. Estimated time for completion: 5
minutes.
2. Highlight the line (setq ANG1 (/ 360 NT)) and choose Inspect.
3. Highlight each component of that same line and inspect them. What sort of
information do you get in the Inspect window for each of these?
8. Double-click on the Entity name. Drill down as far as you can. Notice how many
inspect windows you can get from one object.
FacebookTwitterPinterestEmailPrintShare
The Watch Window allows you to follow the current value of symbol variables as
they are run through the program. If you are having a problem with incorrect data
types being passed to a function you could see the actual information process as it is
happening.
To add a symbol to the window, highlight the symbol name in the program, right-
click, and pick Add Watch. You can also use the Add Watch button and type in the
symbol name.
One useful symbol to watch is the Last Value variable. It keeps track of the last
value used in an expression. To add this to your Watch Window,
select Debug>Watch Last Evaluation from the pull-down menu.
To remove one symbol from the Watch Window, highlight it, right-click and
select Remove from Watch. To clear the entire list, choose the Clear
Window button in the Watch Window.
Animate Mode
The animate mode steps through your program showing each function as it evaluates
it. It is most useful if you also have up the Watch window with the LAST-VALUE
symbol showing. To start it choose Debug>Animate on the pull-down menu. This
is an on/off toggle.
In this practice you will load several symbols into the watch window and then view
them after you have run the routine. You can also work with the Animate mode.
Estimated time for completion: 5 minutes.
1. Open the SAW.LSP file if it is not already open. Add several symbols to the Watch
window.
2. Run the program and then look at the values stored in the Window.
Optional: Animate
1. Highlight the “Get user input” section of the SAW routine and load the selection.
Fill in the information in AutoCAD.
2. Turn Animate on and add LAST-VALUE to the Watch window if it is not already
there.
3. Add several other symbols such as XCEN, YCEN, ANG1, PT1 and PT2 to the watch
window.
4. Highlight the “Perform Calculations” section and load that selection. Watch what
happens as it processes through. Check the values of the symbols.
The (getangle) function measures with the zero-angle at the current base
angle setting in the Units dialog (system variable ANGBASE).
The (getorient) function always measures with the zero-angle to the right
(east, or positive X-axis), regardless of the ANGBASE setting.
The system variable ANGBASE controls the zero (0) direction for angles. By
default it is set to 0, the positive X-axis. If you set it to 90 then zero will be
north or the positive Y-axis. You can use any angle.
The system variable ANGDIR controls the angle direction: 0 for counter-
clockwise (the default) or 1 for clockwise.
Both these functions return a real number representing the value in radians of an
angle entered either by pointing or by typing a value.
Examples
When ANGBASE and ANGDIR are set to the AutoCAD default, both functions give
you the same information:
Command: (getangle)
135
2.35619 135 degrees
Command: (getorient)
135
2.35619 135 degrees
Command: (getangle)
135
2.35619 135 degrees, based on current ANGBASE
Command: (getorient)
135
3.92699 225 degrees, based on default ANGBASE
Further changing the system variable ANGDIR to clockwise (1) results in:
Command: (getangle)
135
3.92699 225 degrees, based on current ANGBASE
Command: (getorient)
135
5.49779 315 degrees, based on default ANGBASE
The angle input by the user is based on the current ANGDIR, but
both (getangle) and (getorient) ignore ANGDIR in the value returned.
If ANGBASE is set to 90, using (getangle) for BLOCK insertions will allow an
input of 0 to equal 0.
If ANGBASE is set to 90, using (getorient) for TEXT insertions will allow an
input of 0 to insert text along the X-axis.
FacebookTwitterPinterestEmailPrintShare
When we execute the (entget) function with the name of a polyline as the argument,
we get a list similar to the following:
Notice that this list contains no information on the vertices of the polyline, while
AutoCAD’s LIST command returns information on each vertex of a polyline.
A similar situation applies to the attributes associated with a block insertion. Block
inserts and polylines are considered complex entities because they consist of
subentities in addition to the main entity itself. There are two functions designed to
access subentities, (entnext) and (nentsel).
Accessing Entity Names and Lists Quickly
For our discussion of subentities we will use two functions that were created in an
earlier module and stored in the GET.LSP file. This will save us a lot of typing, so load
GET.LSP if you created it or type in the following code:
(entnext) takes as its argument an entity name and returns the entity name of the
next entity or subentity. If we execute the following function and pick a polyline, the
entity name returned refers to the main entity:
Executing (entnext) with the entity name of a main entity such as a polyline as
its argument returns a subentity name:
Executing the (entnext) function using the name of a subentity returns the
name of the next subentity:
Thus if the argument is the name of the main entity, the first subentity is returned,
and if the argument is a subentity, the next subentity is returned.
There is a special subentity type called SEQEND, which indicates the end of the list of
subentities. The SEQEND is useful when processing a list of subentities. A polyline
with three vertices, for example, will have a main entity, three subentities with entity
type “VERTEX”, and a fourth subentity, its “SEQEND”:
So far we have only extracted the name of the subentity. To obtain further
information about the subentity, use (entget) with the subentity name as the
argument:
Notice that DXF code 0, entity type, is associated with the string “VERTEX”. Other
DXF codes indicate position, starting and ending width, and other properties relating
to bulge and curvature, depending on how the polyline was created.
In addition to the entity name of the subentity, its entity type and the layer, this list
returns the entity name of the main entity, associated with DXF code -2.
FacebookTwitterPinterestEmailPrintShare
Just as (entnext) works with old style polylines and attributes in a block, it may also
be used to extract the entities that make up a block. This is done through the block
definition table.
The entity name associated with DXF code -2 is the first subentity of the block.
The definition list returned by (entnext) will be the same as for the original
subentity:
(entnext) will find the name of the next subentity in the block:
Command:(entnext SE1)
(Entity name 40000031)
Create SUBEN.LSP, which includes two functions, (suben) and (nextsub), that
will give information about subentities in polylines and blocks. They are printed
below. Estimated time for completion: 10 minutes.
;;; SUBEN.LSP
;;; SUBEN – returns entity definition list
;;; of first subentity of the
;;; selected complex entity
(load “GET”) ;a file we created earlier that
;;;includes the routine GETN
(defun SUBEN ()
(setq SUB (entnext (GETN))) (entget SUB)
)
;** NEXTSUB – returns entity list of next subentity
(defun NEXTSUB ()
(setq SUB (entnext SUB))
(entget SUB)
)
2. Change the PLINETYPE system variable to 0. This allows you to draw old style
polylines.
3. Draw a polyline of two line segments and insert a block named PARTB.
6. Type in (SUBEN) again, select the block insert, and repeat the procedure.
PRACTICE II
Create a function that places a point at each vertex of a polyline. Use the subroutine
technique discussed earlier. Estimated time for completion: 10 minutes.
Steps
1. First create a subroutine that returns a list of subentity names for a selected entity.
2. The main function will process that list and place the points.
Solution (PTPL.LSP)
(defun SUBENT ()
(setq SUBLIST nil)
(setq SUBNAME (car (entsel)))
(setq SUBTYPE (cdr (assoc 0 (entget (entnext SUBNAME)))))
(while (not (= SUBTYPE “SEQEND”))
(setq SUBNAME (entnext SUBNAME))
(setq SUBLIST (cons SUBNAME SUBLIST))
(setq SUBTYPE (cdr (assoc 0 (entget (entnext SUBNAME)))))
))
(defun C:PTPLINE ()
(setvar “cmdecho” 0) (SUBENT)
(setvar “PDMODE” 34)
(foreach SUBNAME SUBLIST
(princ SUBNAME)
(setq ENXY (cdr (assoc 10 (entget subname))))
(command “point” ENXY)
)
(setvar “cmdecho” 0)
)
PRACTICE III
Create the following routine in the file SUBBLK.LSP, that will give the entity
definition list of the first entity in a block. Estimated time for completion: 5 minutes.
;** SUBBLK.LSP
;** SUBBLK-returns the entity definition list of the 1st
;** subentity of a block in the block definition table
(defun SUBBLK ()
(setq B1 (tblnext “BLOCK” T))
(princ (cdr (assoc 2 B1)))
(setq SUB (cdr (assoc -2 B1)))
(entget SUB)
)
Load and execute the above routine, and type in (NEXTSUB) several times.
Polylines
The Entity name is that of the nearest vertex to the selection point.
Blocks
(nentsel) also lets us directly extract information about the entities that make up a
block without accessing the block definition table.
Command: (nentsel)
Select object: Pick an entity in a block insertion (<Entity name: 400000be> (3.0 5.0
0.0) ((1.0 0.0 0.0)
(0.0 1.0 0.0) (0.0 0.0 1.0) (4.0 3.0 0.0)) (<Entity name:600000ea>))
The first two elements of the list are the name of the subentity and the pick
point.
The third element is a list of points designating the model-to-world
transformation matrix, useful in determining the orientation of the UCS both at
the time of creation of the block and at its insertion. (For more information, see
(nentsel) in the AutoLISP Function Catalog of the on-line help.)
The fourth element is the entity name of the block containing the selected
entity or, if the entity picked is part of a nested block, it is the list of the names
of all the nested blocks from innermost to outermost.
Notes
If the object is not a complex object, for example a line, then (nentsel) gives
the same information as (entsel).
Remember, lightweight polylines are not considered complex objects.
Practice
Type in (nentsel) and select various parts of the polyline and block insert.
Estimated time for completion: 5 minutes.
(nentselp) returns the same lists as (nentsel). When a PLINE is selected, it returns
a two-element list similar to the one shown above. When a subentity of a BLOCK is
selected, (nentselp) returns the same seven- element list as that returned
by (nentsel).
PRACTICE
In this practice you will use (nentselp) to extract the vertex of a polyline. Estimated
time for completion: 5 minutes.
1. Define a point using (setq PT1 (getpoint “\nPick: “)).
2. Start the PLINE command, pick a few points, then enter !PT1 for one