TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: FREQUENCYDRIVE on July 23, 2012, 12:19:57 AM

Title: Iterating through blocks dumping all attributes to the command line
Post by: FREQUENCYDRIVE on July 23, 2012, 12:19:57 AM
I am experimenting with some code that basically just dumps to the screen all entity data for a block and if it has attributes it dumps those too.  I just have it dumping to the command line. 

If I select a group of blocks by picking each one my program works fine.  If I select a group of blocks by using a crossing window I get the following error message

; error: bad argument type: lentityp nil

I commented my code before posting it so that some can understand it better.  I also added some information in the comments that may help others troubleshoot my code.

I'm sure the problem is here:  (foreach ent (mapcar 'cadr (ssnamex (setq myss (ssget))))

But how do I fix it so that it doesn't matter what method I use to select the blocks? 

Code - Auto/Visual Lisp: [Select]
  1.  
  2. ;;;
  3. ;;;
  4. ;;; This function steps through a block by interactively picking a block.
  5. ;;; It will dump all the block's attributes in raw form to the command line.
  6. ;;; This is mostly meant as a troubleshooting tool for writing other code.
  7. ;;;
  8.  
  9. (defun StepThroughBlock ()
  10.         (setq Myentitynamecounter 0)
  11.        
  12. ;; If I select entities by picking them one by one ssnamex produces
  13. ;;   (
  14. ;;   (1 <Entity name: 7ffff60ccf0> 2 (0 (9.84626 6.29384 0.0)))
  15. ;;   (1 <Entity name: 7ffff60cf00> 0 (0 (9.86732 6.88025 0.0)))
  16. ;;   )
  17. ;;
  18. ;; If I select entities by picking with a crossing window ssnamex produces
  19. ;;
  20. ;;   (
  21. ;;     (3 <Entity name: 7ffff60cf00> 0 -1)
  22. ;;     (3 <Entity name: 7ffff60ccf0> 0 -1)
  23. ;;     (-1 (0 (9.80865 7.03211 0.0))
  24. ;;       (0 (10.254 7.03211 0.0))
  25. ;;       (0 (10.254 6.16604 0.0))
  26. ;;       (0 (9.80865 6.16604 0.0))
  27. ;;     )
  28. ;;   )
  29. ;;
  30. ;;  So it looks like my problem is in the list that I am passing to "foreach"
  31. ;;  The crossing window produces a third element in the list that I was not
  32. ;;  expecting to get.  I need to fix this because sometime I won't want to
  33. ;;  select each item.  I will want to use a selection window or a crossing
  34. ;;  window.
  35.  
  36.         (foreach ent (mapcar 'cadr (ssnamex (setq myss (ssget))))
  37.                
  38.     ;Find out what the current block name is
  39.                 (setq blockname  (assoc 2 (entget (ssname myss Myentitynamecounter))))
  40.                
  41.     ;Print the name of the current block being processed
  42.                 (head blockname)
  43.                
  44.     ;Initialize attribute counter
  45.                 (setq counter 0)
  46.                
  47.     ;Step inside the first block to the first attribute
  48.     (setq att (entnext ent))
  49.    
  50.     ;;
  51.     ;; Note cdadr is the same as (cdr (cadr))
  52.     ;;
  53.                 (while (not (eq "SEQEND" (cdadr (entget att))))
  54.                         (princ (entget att))
  55.                         (princ "\n\n")
  56.                         (setq att (entnext att))
  57.                         (setq counter (1+ counter))
  58.                        
  59.                 )
  60.                 (tail counter)
  61.                
  62.                 (setq Myentitynamecounter (1+ Myentitynamecounter))
  63.                
  64.         )
  65.        
  66.         (printOnExit Myentitynamecounter)
  67. )
  68. (defun tail (counter)
  69.      (princ (strcat "\n\n(((((((((((((((((((  Total number of attributes is " (itoa counter) ")))))))))))))))))))\n\n"))
  70.      (princ)
  71. )
  72. (defun head (blockname)
  73.      (princ (strcat "\n-----------------------  "  (vl-princ-to-string (cdr blockname)) "  -----------------------\n"))
  74. )
  75. (defun printOnExit (Myentitynamecounter)
  76.      (princ (strcat "\n\n------------------- Total number of blocks selected was " (itoa  Myentitynamecounter) " -------------------\n\n"))
  77.  
  78. )
  79.                
  80.  
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: Tharwat on July 23, 2012, 02:27:22 AM
This ... ?

Code - Auto/Visual Lisp: [Select]
  1. (defun c:TesT (/ ss n e)
  2.   ;; Tharwat 16. Nov. 2011 ;;
  3.   (while
  4.     (setq ss (ssget "_+.:S" '((0 . "INSERT") (66 . 1))))
  5.      (setq n (entnext (ssname ss 0)))
  6.      (while
  7.        (not (eq (cdr (assoc 0 (setq e (entget n)))) "SEQEND")
  8.        )
  9.         (if (eq (cdr (assoc 0 e)) "ATTRIB")
  10.           (print e)
  11.         )
  12.         (setq n (entnext n))
  13.      )
  14.   )
  15.   (princ)
  16. )
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: roy_043 on July 23, 2012, 05:12:20 AM
@ FREQUENCYDRIVE:

You should read the Help regarding ssnamex:
Quote from: http://docs.autodesk.com/ACD/2011/ENU/filesALR/WS1a9193826455f5ff1a32d8d10ebc6b7ccc-6933.htm
... If the index argument is not supplied, this function returns a list containing the entity names of the elements in the selection set, along with data that describes how each entity was selected.

If you use the code below you will remove this data from your list:
Code - Auto/Visual Lisp: [Select]
  1. (vl-remove-if 'listp (mapcar 'cadr (ssnamex (ssget))))


Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: ElpanovEvgeniy on July 23, 2012, 05:42:05 AM
Code - Auto/Visual Lisp: [Select]
  1. (mapcar 'cadr (ssnamex (ssget "_x" '((0 . "line")))))
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: irneb on July 23, 2012, 05:44:43 AM
Just remember, the ssnamex function is slower than using an index and applying it to ssname in  loop. http://forums.augi.com/showthread.php?121467-Selection-Set-Performance (http://forums.augi.com/showthread.php?121467-Selection-Set-Performance)
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: Lee Mac on July 23, 2012, 08:11:43 AM
You might find this program useful:

http://lee-mac.com/entitylist.html (http://lee-mac.com/entitylist.html)
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: irneb on July 23, 2012, 08:51:20 AM
What I'm referring to is this: Comparing a ss to list convertion (say Lee's http://lee-mac.com/selectionsettolist.html) to the mapcar on ssnamex:
Code - Auto/Visual Lisp: [Select]
  1. (defun slow:ss->ent (ss / )
  2.   (mapcar 'cadr (ssnamex ss)))
Here's a benchmark:
Code: [Select]
_$ (setq ss (ssget "_X"))
<Selection set: 150b>
_$ (sslength ss)
6251
_$ (QuickBench '((LM:ss->ent ss) (slow:ss->ent ss)))
Benchmarking .. done for 128 iterations. Sorted from fastest.
Statement                                Increment  Time(ms) Normalize  Relative
--------------------------------------------------------------------------------
(LM:SS->ENT SS)                                128      1325      1325      3.35
(SLOW:SS->ENT SS)                               32      1109      4436      1.00
--------------------------------------------------------------------------------
More than 3 times as slow.
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: FREQUENCYDRIVE on July 24, 2012, 03:01:44 AM
@ FREQUENCYDRIVE:

You should read the Help regarding ssnamex:
Quote from: http://docs.autodesk.com/ACD/2011/ENU/filesALR/WS1a9193826455f5ff1a32d8d10ebc6b7ccc-6933.htm
... If the index argument is not supplied, this function returns a list containing the entity names of the elements in the selection set, along with data that describes how each entity was selected.

I actually had that help document right in front of me while troubleshooting my code.  I still felt like I needed help.

I tried the line:

Code: [Select]
(vl-remove-if 'listp (mapcar 'cadr (ssnamex (ssget))))

It didn't work, but it's probably because I'm not using it in the way you intended.  I took your code segment above and pasted into the foreach statement so that I now have:

Code: [Select]

(foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex (ssget))))

code here but not shown

);end foreach

I'm probably doing something stupid.  It's 2AM so I'll sleep on this and try to figure out what the "vl-remove-if" does.  I've never seen that before.


Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: FREQUENCYDRIVE on July 24, 2012, 03:03:17 AM
You might find this program useful:

http://lee-mac.com/entitylist.html (http://lee-mac.com/entitylist.html)

Lee you have a nice website.  I love the mathematics section.  I just bookmarked it.  I'll be back there often for sure.
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: FREQUENCYDRIVE on July 24, 2012, 03:20:04 AM
This ... ?

Code - Auto/Visual Lisp: [Select]
  1. (defun c:TesT (/ ss n e)
  2.   ;; Tharwat 16. Nov. 2011 ;;
  3.   (while
  4.     (setq ss (ssget "_+.:S" '((0 . "INSERT") (66 . 1))))
  5.      (setq n (entnext (ssname ss 0)))
  6.      (while
  7.        (not (eq (cdr (assoc 0 (setq e (entget n)))) "SEQEND")
  8.        )
  9.         (if (eq (cdr (assoc 0 e)) "ATTRIB")
  10.           (print e)
  11.         )
  12.         (setq n (entnext n))
  13.      )
  14.   )
  15.   (princ)
  16. )

That code is very succinct. I like it but,  I don't understand this part:
Code: [Select]
(ssget "_+.:S"
I have the autolisp reference manual (1992) that  I got from an old'timer at work.  I assume those characters after ssget "_+.:S" are filters of some sort.  I'll have to dig into that more.  Off to the online help to figure out what that means.

Thank you all for your help.  Eventually I would have figured all this out but posting to this forum has opened up a lot of other things about SSGET that I didn't know.  I really appreciate the help.
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: Lee Mac on July 24, 2012, 07:05:39 AM
You might find this program useful:

http://lee-mac.com/entitylist.html (http://lee-mac.com/entitylist.html)
Lee you have a nice website.  I love the mathematics section.  I just bookmarked it.  I'll be back there often for sure.

Thanks FREQUENCYDRIVE, I'm glad you like it!  :-)

I don't understand this part:
Code: [Select]
(ssget "_+.:S"
I have the autolisp reference manual (1992) that I got from an old'timer at work.  I assume those characters after ssget "_+.:S" are filters of some sort.

The string "_+.:S" is a combination of a number of ssget mode strings, each component of which has a different meaning:

"_" (underscore) allows for variation in language; prefixing mode string operators with an underscore forces the English version.

"+." This undocumented mode string forces ssget to remain in 'point' mode, similar to setting PICKAUTO to 0.

":S" As stated in the Visual LISP IDE Help Documentation, this mode string forces a single selection, that is, the user may attempt to select a number of objects only once. When combined with the "+." mode string, this forces a single object selection.

However, there are numerous other undocumented ssget mode strings and so, to benefit both you and the community, I have attached all of the information that I have collected on the ssget function from various sources.


« Edited to correct erroneous description of ":S", as stated in Reply #11 (http://www.theswamp.org/index.php?topic=42316.msg474866#msg474866) »
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: roy_043 on July 24, 2012, 04:07:52 PM
":S" As stated in the Visual LISP IDE Help Documentation, this mode string forces single object selection only.

Quote from: http://docs.autodesk.com/ACD/2011/ENU/filesALR/WS1a9193826455f5ff1a32d8d10ebc6b7ccc-693e.htm
:S Allow single selection only.

I have been told that "single selection" should be interpreted as "single selection PASS" not as "single OBJECT selection". A single selection pass means the user can select only once, but if a window or crossing is used multiple objects can be selected. Which explains why "+." is required.
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: Lee Mac on July 24, 2012, 05:10:16 PM
":S" As stated in the Visual LISP IDE Help Documentation, this mode string forces single object selection only.

Quote from: http://docs.autodesk.com/ACD/2011/ENU/filesALR/WS1a9193826455f5ff1a32d8d10ebc6b7ccc-693e.htm
:S Allow single selection only.

I have been told that "single selection" should be interpreted as "single selection PASS" not as "single OBJECT selection". A single selection pass means the user can select only once, but if a window or crossing is used multiple objects can be selected. Which explains why "+." is required.

You are absolutely right roy, I shall reword my post and information file.

EDIT: Above post and attached Text file updated to correct erroneous description of :S mode string.
Thank you for highlighting those mistakes roy :)
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: CAB on July 24, 2012, 06:32:26 PM
FREQUENCYDRIVE
This is an old routine you may want to take a look at.
http://www.theswamp.org/index.php?topic=1173.0
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: FREQUENCYDRIVE on July 26, 2012, 12:34:16 AM
FREQUENCYDRIVE
This is an old routine you may want to take a look at.
http://www.theswamp.org/index.php?topic=1173.0

Wow that is exactly the code I was trying to write.  Perfect.  Thanks CAB.
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: FREQUENCYDRIVE on July 26, 2012, 12:39:08 AM
Quote
The string "_+.:S" is a combination of a number of ssget mode strings, each component of which has a different meaning:

"_" (underscore) allows for variation in language; prefixing mode string operators with an underscore forces the English version.

"+." This undocumented mode string forces ssget to remain in 'point' mode, similar to setting PICKAUTO to 0.

":S" As stated in the Visual LISP IDE Help Documentation, this mode string forces a single selection, that is, the user may attempt to select a number of objects only once. When combined with the "+." mode string, this forces a single object selection.

However, there are numerous other undocumented ssget mode strings and so, to benefit both you and the community, I have attached all of the information that I have collected on the ssget function from various sources.


« Edited to correct erroneous description of ":S", as stated in Reply #11 (http://www.theswamp.org/index.php?topic=42316.msg474866#msg474866) »

Lee,

If some of those are undocumented how did you ever find out about them?  Stuff like that really bothers me.  I'm trying to learn Lisp to make my life easier then I found out everyone knows about some "undocumented" feature that may, just may have made my life easier.  How did you... or how do you find out these things.  Inside connections at Autodesk?

Again thank you for the file you uploaded.  You really are doing a service to the rest of us on here struggling to learn lisp and Autocad.  The same goes for CAB.
Title: Re: Iterating through blocks dumping all attributes to the command line
Post by: Lee Mac on July 26, 2012, 08:16:02 AM
If some of those are undocumented how did you ever find out about them?

In my experience, undocumented features and functions can be found in a number of ways, some are leaked by those with connections to Autodesk and then collected, compiled and passed around the various discussion groups and forums (as I have done in my earlier post).

Other functions can be found through careful analysis of the atoms-family list of protected symbols or the Apropos utility in the Visual LISP IDE, followed by a lot of trial and error experimentation to determine the purpose and arguments required by each function.

Consider, for example, the Vanilla and Visual LISP functions: pragma, vl-bt, vl-infp, vl-nanp, vl-init, bherrs, xstrcase, fnsplitl to name a few; or the VLIDE functions _vl-times, _vl-balance-parenthesis, _vl-fast-mode; not to mention the entire set of vlisp-* functions used for VLX compilation (none of which are documented); and then there are the hundreds (http://www.theswamp.org/index.php?topic=13719) of Express Tools acet-* functions, of which, only a few are documented.

Other features can be found simply through experimentation with existing functions.

Again thank you for the file you uploaded.  You really are doing a service to the rest of us on here struggling to learn lisp and Autocad.  The same goes for CAB.

You're welcome, I'm glad it helps  :-)