Extended Entity Data
What is Extended Entity Data?
For years AutoCAD has had the ability to store user information within a drawing by utilising attributes. But, attributes have got their limitations. They've got to be a block, or part of a block. They can be difficult to use. They can be exploded or modified by the user and they can only hold certain types of information.
Extended Entity Data though, allows you to attach up to 16K of information to each and every entity in the drawing. You can also keep it totally separate from other information and, because it uses a uniquely registered name, can be kept relatively safe from being overwritten. You can also store lot's of different types of information in Extented Entity Data.
Extended Entity Data is attached to an entity as an associated list with a code number of -3. The simplest form of an Xdata Associative list would look something like this :
((-3 ("AFRALISP" (1000 . "Kenny is great"))))
Firstly, let's look at some of the different types of xdata that you can attach to an entity :
Data Type | Code | Description |
---|---|---|
String | 1000 | A string of up to 255 characters. |
Application Name | 1001 | An Application Name. |
Layer Name | 1003 | The name of a Layer. |
DataBase Handle | 1005 | The handle of an entity. |
3D Point | 1010 | A 3D Coordinate value. |
Real | 1040 | A real value. |
Integer | 1070 | A 16 bit integer (signed or unsigned). |
Long | 1071 | A 32 bit signed (long) integer. |
Control String | 1002 | A control code to set off nested list. |
World Space Position | 1011 | A 3D coordinate point that is moved, scaled rotated, streched and mirrored along with the entity. |
World Space Displacement | 1012 | A 3D coordinate point that is scaled, rotated or mirrored along with the entity. It cannot be stretched. |
World Space Direction | 1013 | A 3D coordinate point that is rotated or mirrored along with the entity. It cannot be scaled, streched or moved. |
Distance | 1041 | A real value that is scaled along with the entity. Used for distance. |
Scale Factor | 1042 | A real value that is scaled along with the entity. Used as a scale factor. |
Another important thing to remember about Xdata is that you can have more than one of the same associative code.
Let's attach some xdata to an entity in a drawing. Draw a line then type this:
(regapp "AFRALISP")
AutoLisp should return :
"AFRALISP"
You have now registered your external entity data name. This name is a unique identifier to your own extended entity data. Next we need to get the entity data list of the entity that we want to add exdata to. Type this :
(setq oldlist (entget (car (entsel))))
AutoLisp should return something like this :
Select object: ((-1 . <Entity name: 2100888>) (0 . "LINE") (5 . "271") (100 . "AcDbEntity") (67 . 0) (8 . "0") (100 . "AcDbLine") (10 336.561 591.45 0.0) (11 672.362 497.304 0.0) (210 0.0 0.0 1.0))
Now, let's create the exdata that we want to add to the entity :
(setq thedata '((-3 ("AFRALISP" (1000 . "Kenny is handsome") (1000 . "And intelligent")))))
Append it to the entity data list :
(setq newlist (append oldlist thedata))
Now, update the entity :
(entmod newlist)
We have now attached the xdata to the entity. To retrieve it we would type this :
(setq elist (entget (car (entsel)) '("AFRALISP")))
This would return the modified entity list. It should look something like this :
Select object: ((-1 . <Entity name: 2100888>) (0 . "LINE") (5 . "271") (100 . "AcDbEntity") (67 . 0) (8 . "0") (100 . "AcDbLine") (10 336.561 591.45 0.0) (11 672.362 497.304 0.0) (210 0.0 0.0 1.0) (-3 ("AFRALISP" (1000 . "Kenny is handsome") (1000 . "And intelligent"))))
To retrieve the xdata we would type this :
(setq exlist (assoc -3 elist))
This gets the xdata list from the entity list.
(-3 ("AFRALISP" (1000 . "Kenny is handsome") (1000 . "And intelligent")))
To retrieve the xdata itself we would type this :
(setq thexdata (car (cdr exlist)))
Now, we should have this :
("AFRALISP" (1000 . "Kenny is handsome") (1000 . "And intelligent"))
We now have an ordinary list. Because we created the xdata list, and we know in what order we created it, it's very simple to retrieve each individual part :
(setq data1 (cdr (nth 1 thexdata))) (setq data2 (cdr (nth 2 thexdata)))
This should return :
"Kenny is handsome" "And intelligent"
This, of course, is a factual statement.
Using Extended Entity Data
We are now going to write an application that attaches, as Extended Entity Data, bolt details to holes in a drawing. The details we will store will be Bolt Size, Bolt Length and Bolt Grade. We will design a dialogue box to enter this data. If no data has been attached, the application will firstly attach some default data and then allow you to edit this. If data has been already attached, it will display this data and then allow you to change it, if you so wish.
Let's look at the Dialogue Box Coding first :
exbolt : dialog { //dialog name label = "Bolt Details"; //give it a label : boxed_row { //start boxed row label = "Choose Size and Length"; //give it a label : popup_list { //define list box key = "sel1"; //give it a name } //end list : popup_list { //define list box key = "sel2"; //give it a name } //end list } //end boxed row : boxed_radio_row { //start boxed radio row label = "Choose Grade"; //give it a label : radio_button { //define radio button key = "rb1"; //give it a name label = "4,6"; //give it a label } //end radio button : radio_button { //define radio button key = "rb2"; //give it a name label = "8,8"; //give it a label } //end radio button : radio_button { //define radio button key = "rb3"; //give it a name label = "H.S.F.G."; //give it a label } //end radio button } //end boxed radio row ok_cancel ; //predifined OK/Cancel } //end dialog
And now the AutoLisp code:
(defun c:exbolt ( / ) ;define function (setvar "cmdecho" 0) ;switch off command echo (prompt "\nSelect the Hole to Add/Modify Xdata : ") ;prompt the user (setq e (entget (car (entsel)) '("AFRALISP"))) ;get the associative code list (setq e1 (assoc -3 e)) ;get the xdata (if (not e1) ;if there is no exdata (progn ;do the following (if (not (tblsearch "APPID" "AFRALISP")) ;check if the application has been registered (regapp "AFRALISP") ;if not, register it );if (setq e1 '((-3 ("AFRALISP" (1000 . "3") (1000 . "3") (1000 . "8,8") )))) ;create a default xdata list (setq e (append e e1)) ;append to to the main list (entmod e) ;modify the entity );progn );if (setq e2 (assoc -3 e)) ;get the code -3 list (setq e3 (car (cdr e2))) ;get the exdata list (setq SIZ (cdr (nth 1 e3))) ;get the bolt size index number (setq SIZ1 (cdr (nth 2 e3))) ;get the bolt length index number (setq gr (cdr (nth 3 e3))) ;get the bolt grade (setq userclick T) ;set flag (setq NAMES '("M6" "M8" "M10" "M12" "M16" "M20" "M24" "M30" "M36")) ;create list of bolt sizes (setq LEN '("10" "15" "20" "25" "30" "35" "40" "45" "50" "55" "60")) ;create list of bolt lengths (setq dcl_id (load_dialog "exbolt.dcl")) ;load dialogue (if (not (new_dialog "exbolt" dcl_id) ;check for errors );not (exit) ;if problem exit );if (set_tile "sel1" SIZ) ;initilise list box (set_tile "sel2" SIZ1) ;initilise list box (start_list "sel1") ;start the list (mapcar 'add_list NAMES) ;add the bolt size (end_list) ;end the list (start_list "sel2") ;start the list (mapcar 'add_list LEN) ;add the lengths (end_list) ;end the list (cond ;on condition ((= gr "4,6") (set_tile "rb1" "1")) ;if GR 4,6 switch on radio button rb1 ((= gr "8,8") (set_tile "rb2" "1")) ;if GR 8,8 switch on radio button rb2 ((= gr "HSFG") (set_tile "rb3" "1")) ;if GR HSFG switch on radio button rb3 );end cond (action_tile "rb1" ;if radio button rb1 selected "(setq gr \"4,6\")" ;set grade of bolt );action_tile (action_tile "rb2" ;if radio button rb2 selected "(setq gr \"8,8\")" ;set grade of bolt );action_tile (action_tile "rb3" ;if radio button rb3 selected "(setq gr \"HSFG\")" ;set grade of bolt );action_tile (action_tile "cancel" ;if cancel selected "(done_dialog) ;end dialog (setq userclick nil)" ;set flag to nill );action_tile ;if cancel set flag to nil (action_tile "accept" "(setq siz (get_tile \"sel1\")) ;get the bolt size (setq siz1 (get_tile \"sel2\")) ;get the bolt length (done_dialog) ;end the dialog (setq userclick T)" ;set the flag to true );action tile (start_dialog) ;start the dialogue (unload_dialog dcl_id) ;unload the dialogue (if userclick ;if OK has been selected (progn ;do the following (setq NSIZ (cons 1000 SIZ)) ;construct a new bolt size list (setq NSIZ1 (cons 1000 SIZ1)) ;construct a new bolt length list (setq NGR (cons 1000 gr)) ;construct a new bolt grade list (setq e4 (chnitem NSIZ 2 e3)) ;change the existing bolt size list (setq e5 (chnitem NSIZ1 3 e4)) ;change the existing bolt length list (setq e6 (chnitem NGR 4 e5)) ;change the existing bolt grade list (setq e7 (subst e6 e3 e2)) ;update list (setq e8 (subst e7 e2 e)) ;update list (entmod e8) ;update the entity (setq SIZ (nth (atoi SIZ) NAMES)) ;get the size of the bolt from the list (setq SIZ1 (nth (atoi SIZ1) LEN)) ;get the length of the bolt from the list (alert (strcat "The size of bolt is " SIZ "\n" "The length of bolt is " SIZ1 "\n" "The grade of bolt is " GR) );alert );end progn );end if (princ) ;finish cleanly );end defun ;;This function replaces any element in a list with another element ;;It requires 3 parameters (chnitem value itemnumber list) (defun chnitem (value num lst) (setq num (- num 1)) (setq tmplt (list nil)) (setq tmplt2 (list nil)) (setq counter 0) (repeat num (setq tmplt (append tmplt (list (nth counter lst)))) (setq counter (+ counter 1)) ) (setq counter (+ counter 1)) (repeat (- (length lst) (+ num 1)) (setq tmplt2 (append tmplt2 (list (nth counter lst)))) (setq counter (+ counter 1)) ) (setq tmplt (cdr tmplt)) (setq tmplt2 (cdr tmplt2)) (setq lst (append tmplt (list value) tmplt2)) ) (princ) ;load cleanly
Draw a few circles representing holes on your drawing and run this application. Clever, hey?
Now, let's write a routine that extracts this data from the drawing and saves it, in a space deliminating format, to an external text file.
(defun C:exfile () ;define the function (setq NAMES '("M6" "M8" "M10" "M12" "M16" "M20" "M24" "M30" "M36")) ;create list of bolt sizes (setq LEN '("10" "15" "20" "25" "30" "35" "40" "45" "50" "55" "60")) ;create list of bolt lengths (setq fname (getstring "\nEnter file name: ")) ;get the file name (setq fn (open fname "w")) ;open it to write (setq a (ssget "x" '((-3 ("AFRALISP"))))) ;get all the bolt exdata in the drawing (setq lg (sslength a)) ;get the number of bolts (setq i 0) ;set counter to zero (repeat lg ;repeat for the number of entities with bolt xdata (setq e (entget (ssname a i) '("AFRALISP"))) ;get the entity list (setq i (1+ i)) ;increment the counter (setq d (assoc -3 e)) ;get the xdata list (setq d1 (cdr (car (cdr d)))) ;get just the xdata (mapcar 'set '(SIZ SIZ1 GR) d1) ;put each of the lists into variables (setq SIZ (cdr SIZ)) ;get the index number of the bolt size (setq SIZ (nth (atoi SIZ) NAMES)) ;retrieve the bolt size from the master list (setq SIZ1 (cdr SIZ1)) ;get the index number of the bolt length (setq SIZ1 (nth (atoi SIZ1) LEN)) ;retrieve the bolt size from the master list (setq GR (cdr GR)) ;retrieve the bolt grade (princ SIZ fn) ;print bolt size (princ " " fn) ;print a space (princ SIZ1 fn) ;print bolt length (princ " " fn) ;print a space (princ GR fn) ;print the bolt grade (princ "\n" fn) ;print a new line );end repeat (close fn) ;close the file (alert (strcat "Exported Details of\n" (itoa lg) " Bolts to file : \n" (strcase fname)) );alert ;inform the user (princ) ;finish cleanly );end defun (princ) ;load cleanly
As you can see, you can attach xdata to any type of entity, and attach all sorts of different types of information.
Well, that's about it for now. If you would like the source coding for the applications written on this page, then just click here.
출처 : https://www.afralisp.net/autolisp/tutorials/extended-entity-data-part-1.php
'Auto CAD > lisp' 카테고리의 다른 글
달수가 생각하는 VisualLISP 과 Excel 연동 2 (0) | 2019.04.04 |
---|---|
TGK - 태극기 그리기 (0) | 2019.02.04 |
SetTextHeight Method (ActiveX) (0) | 2019.01.23 |
Reactors - Part 1 (0) | 2018.12.28 |
폭파하지 못하는 블록을 폭파 가능하게 만드는 리습 (0) | 2018.12.27 |