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.
Creating New Association Pairs
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.
Explanation: the (cons) function with DXF codes
(cons new_first_element list)
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:
Command: (cons 10 PT1)
(10 1.0 1.0 0.0)
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.
(cons new_first_element atom)
For example, if we wanted to create a new association pair that represented the layer WALLS:
Command: (cons 8 “WALLS”)
(8 . “WALLS”)
Tip: (cdr) with Dotted Pairs and Lists
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”))
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)
Substituting one Association Pair for Another
To switch association pairs we will need to use a new command, the (subst) function.
Explanation: the (subst) function
(subst new_item old_item list)
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:
Command: (setq OLDLAY (assoc 8 ELIST1))
(8 . “0”)
Command: (setq NEWLAY (cons 8 “WALLS”))
(8 . “WALLS”)
Command: (setq NEWENT1 (subst NEWLAY OLDLAY ELIST1))
Updating the Entity in the Drawing
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.
Explanation: the (entmod) function
The (entmod) function updates the drawing database for the entity whose name is specified by the “-1” DXF code , or entity name, in ename.
Command: (entmod ENAME)
((-1 . <Entity name: 60000014> (0 . “LINE”) (8 .”WALLS”) (5 . “15”) (10 1.0 9.0 0.0) (11 5.0 8.0 0.0) (210 0.0 0.0 1.0))
Tip: Changing Subentities
If changes are made to a subentity (e.g. vertex of a pline or attribute of a block), an additional step is required to update the drawing by using the (entupd) function:
The (entupd) function causes the modified pline or block with name ename to be updated on the screen. It may be used with any entity, and simply causes that entity to be regenerated. See the Appendix for more information about working with subentities.
Create a function, CHANGEBLOCK.LSP, that will enable you to replace one block with another user-designated block. Estimated time for completion: 10 minutes.
(defun C:CHANGEBLOCK ()
(setq ENT (car (entsel “Select block to replace: “))
NEWBLOCKNAME (getstring “New block name: “)
(if (/= NEWBLOCKNAME “”)
(setq OLDELIST (entget ENT)
OLDBLOCKNAMELIST (assoc 2 OLDELIST)
NEWBLOCKNAMELIST (cons 2 NEWBLOCKNAME)
NEWELIST (subst NEWBLOCKNAMELIST OLDBLOCKNAMELIST OLDELIST)
(prompt “\nA block name was not entered.”)
Open the drawing BLOX.DWG and load the function. Use the CHANGEBLOCK function to change the block FROWN to SMILE.
- A complete solution to this exercise is on your class disk as CHANGEBLOCK-A.LSP.
Automatically Updating an Object
Just as we previously created a user-defined function, (getdxf), to isolate the data associated with a certain DXF code, you will find it convenient to create a user-defined function to automatically update an entity based on the DXF code number, the new value for that DXF code number, and an ename.
(defun SETDXF (CODE NEWVALUE ENAME)
(cons CODE NEWVALUE)
(assoc CODE (entget ENAME))
) ; end subst
) ; end entmod
) ; end defun
- A complete solution to this exercise is on your class disk as SETDXF-A.LSP.
Tip: Modularity in Programming
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 ( )
;;;GETLIST – returns the Entity List
;;;of the selected entity
(defun GETLIST ( )
(entget (car (entsel)))