From: vnestr@netvision.net.il (Vladimir Nesterovsky) Newsgroups: comp.cad.autocad Subject: Re: R13 3D Solids Date: Fri, 08 Nov 1996 14:55:28 GMT Hello, On Thu, 07 Nov 1996 22:39:46 +0100 Morten Warankov wrote: >[...] I really would appreciate if you could >show me how to rewrite a lisp that I know how works. >I recon that a routine like this would be a good place to use mapcar. >A copy of the article in cca follows::::::::::::::::::::: > >Paul Kohut wrote: >> Dennis Shinn wrote in article >[...] > >PS. I think this would be a great opportunity to ask Vladimir to convert >this to mapcar's and lambda's. Just for the amusement for Lu and myself. > >;; Routine to retrive entity data for 3D objects. >;; Written by Morten Warankov (c) ABACUS 1996. >;; Selecting the 3D object and this routine returns the entity data >(defun c:getentity ( / ) > (setq test1 (entget (car (entsel)))) > (foreach i test1 > (if (= (car i) 1) > .................. I guess you don't need to keep other fields here, only 1's, and then decrypt them. owenw@manusoft.com (Owen Wengerd) has posted this version on c.c.a. : ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun ACISdecode (st / ln n c st1) (setq st1 "" n (strlen st)) (while (> n 0) (setq c (ascii (substr st n 1))) (setq st1 (strcat (cond ((= c 32) " ") ((= c 86) "I") ((chr (boole 6 c 95)))) st1)) (setq n (1- n))) st1 ) ........................... (foreach lt ed (if (= (car lt) 1) (setq st (strcat "\n" (ACISdecode (cdr lt)) st))))) ;; ^^^^^^ added as Paul Kohut stated ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; This is indeed very fine and efficient code. I don't know if all the mapcar~s here would add something. In fact they may slow down the execution. I myself prefer FOREACH over MAPCARs, when appropriate. It consumes far less node space causing less garbage collections and thus speeding things up on BIG data. On the other hand we may achieve shorter code, and this means less time spent by interpretor interpreting the source at run-time. There're usually less SETQs that take time also, and MAPCARs help to avoid this. Another factor is maintenace and coding in the first place. If I have those list-processing routines handy it's very tempting to use them. What I usually find later when fine-tuning the code is that all this have cost. If execution time is really a question, then try to 'inline' as much functions as you can. For example, STRTOL converts string to list of its characters. Then I apply ACIS_DECODE on each and gather them back. But I may as well convert them on-fly inside STRTOL_WITH_ACIS_DECODE (a special version that needs to be built) thus avoiding the whole unnecessary MAPCAR cycle. The real problem as we see now is that AutoLISP has NO inlining. I know C++ has it, that's why STL is so efficient. I've heard that some other (real) LISPs has it to with DEFMACRO. We don't. Back to the issue, using MAPCARs at large. We need first get the entity data, then for each 1-dxf group of it - get the string - turn it into a list of its characters with STRTOL - apply on each char DECODE function (by Owen Wengard's code) - gather the char-list back into string Then we eliminate unwanted code groups by turning them into NILs and applying append [see LISP PUZZLE for that] like (apply 'append list-of-lists-or-nils) ;; by Vladimir Nesterovsky, vnestr@netvision.net.il (defun c:show3d( / d decode ) ;;GLOBALS: datalist datastr (if (member(cdr(assoc 0 (setq d (entget(car(entsel "\nPick an object: ")))))) '("3DSOLID" "REGION"))(progn (defun decode(s) ;; decode a string (apply'strcat(mapcar'(lambda(c) ;; decode one char (cond ;; by Owen Wengerd ((= (setq c (ascii c)) 32) " ") ((= c 86) "I") (T (chr (boole 6 c 95))))) (strtol s)))) (setq datalist ;; list of converted strings (apply 'append ;; remove all NILs and open all lists (mapcar ;; that have artificially been built '(lambda(a) ;; take strings out ---------------------+ (if(= 1(car a))(list ;; if dxf-code is 1 | (decode(cdr a))) ;; decode the string | nil)) ;; skip the unrelevant codes | d))) ;; of entget <---------------------------+ ;; here we may further analyze the data, may be it must be ;; reversed (at least Owen builds it that way) etc... ;; print the list one-by-one now: (lp11 datalist) ;; or to get one result string (setq datastr (strgather datalist "\n")) (princ) ) (princ "\nNot an ACIS Object!") ) (princ) ) ;;use this to print list one-by-one (defun lp11(l) (foreach e l (print e)(read-char))) ;;turn string into list of characters (defun strtol ( s / l c ) (repeat (setq c (strlen s)) (Setq l (cons (substr s c 1) l) c (1- c) )) l ) ;;gather strings list back to string, inserting delims in between. (defun strgather( sl delims ) (substr (apply 'strcat (mapcar'(lambda(s)(strcat delims s)) sl)) (1+ (strlen delims)))) If you want just to convert encoded strings inside entity data, you may use (defun dec-ed(ed) (mapcar '(lambda(a) (if(/= 1(car a))a (cons 1 (decode (cdr a)))))ed)) So the function becomes (with no error checking): (defun c:show3d() (lp11 (dec-ed (entget(car(entsel"\nPick a 3d object, please: ")))))) -- Vladimir Nesterovsky LISP/C/C++ etc. 11/08/96 10:59:15 P.S. As your original intent I'm posting this in newsgroup too, in the thread 'R13 3D Solids' where all this began.