Author Topic: There's got to be a better way  (Read 10665 times)

0 Members and 1 Guest are viewing this topic.

nivuahc

  • Guest
There's got to be a better way
« on: December 01, 2005, 09:23:54 AM »
There's got to be a better way

I posted a tiny bit of code in this thread earlier today that I threw together yesterday when my brain took a detour from work for a bit. Anyway, I threw it together because I wanted to refresh my mind a bit when it comes to building lists and processing them (I haven't written any code in forever and I have a framework of an idea for a routine, this being part of it).

Anyway, what I actually wanted to do was build a list of layers that I could parse through and this is what I came up with:

Code: [Select]
;*********************************************************************************
; Function to build a list of available layers - © Copyright 2005 by Chuck Chauvin
;*********************************************************************************
(defun BuildLayerList (/ LayerItem)
  (setq LayerList nil)
  (setq LayerItem (tblnext "LAYER" T))

  (while (/= LayerItem nil)
    (setq LayerList
   (append LayerList
   (list
     (list
       (cdr (assoc 2 LayerItem))  ;; Name
       (cdr (assoc 62 LayerItem)) ;; Color
       (cdr (assoc 6 LayerItem))  ;; Linetype
     ) ;_end list
   ) ;_end list
   ) ;_end append
    ) ;_end setq LayerList
    (setq LayerItem (tblnext "LAYER"))
  ) ;_end while
 
  (princ)
) ;_end defun BuildLayerList

This started out as me thinking "build a list of layers that are in the drawing along with their linetypes". That was simple enough to do but, along the way I thought "well, maybe I'll want to throw the color in there as well" so I added that bit as an afterthought. Anyway, the above code will build a list that looks like this:

Code: [Select]
(("0" 7 "Continuous") ("LAYER_1" 7 "Continuous") ("LAYER_2" 5 "Dashed") ("LAYER_3" 150 "Hidden"))
that I can then use later on, in this skeleton of a routine I've got floating around in my skull.

Anyway, my gut tells me this isn't the most efficient way (with LISP) to do this and I was wondering if anyone had any thoughts or suggestions (using LISP) to make this better.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: There's got to be a better way
« Reply #1 on: December 01, 2005, 09:31:08 AM »
Chuck, Thats about as efficient as you'll get .. if you consider return on investment, and if you're not chasing milliseconds.

I have a similar functionality using Vlisp which grabs the Layers Collection and iterates it collecting the properties from each Layer object, including some status info.  I doubt it is much faster or slower than yours.

 
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Jόrg Menzi

  • Swamp Rat
  • Posts: 599
  • Oberegg, Switzerland
Re: There's got to be a better way
« Reply #2 on: December 01, 2005, 09:49:19 AM »
That's what I would use
Code: [Select]
(defun BuildLayerList ( / LayerItem LayerList)
 (while (setq LayerItem (tblnext "LAYER" (not LayerItem)))
  (setq LayerList
   (cons
    (list
      (cdr (assoc 2 LayerItem))  ;; Name
      (cdr (assoc 62 LayerItem)) ;; Color
      (cdr (assoc 6 LayerItem))  ;; Linetype
    ) ;_end list
    LayerList   
   ) ;_end append
  ) ;_end setq LayerList
 ) ;_end while
 (reverse LayerList)
) ;_end defun BuildLayerList
Using 'cons' instead of 'append' is remarkable faster... and 'tblnext' can be controlled by his return value. Note, the LayerList variable isn't anymore global. The function returns the value now, strictly speaking the correct way to program sub's.

Cheers :-)
A computer's human touch is its unscrupulousness!
MENZI ENGINEERING GmbH
Current A2k16... A2k24 - Start R2.18

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: There's got to be a better way
« Reply #3 on: December 01, 2005, 09:54:59 AM »
Code: [Select]
(defun ForFun ( / data result )
    (while (setq data (tblnext "layer" (null data)))
        (setq result
            (cons
                (mapcar
                   '(lambda (key) (cdr (assoc key data)))
                   '(2 62 6)
                )
                result
            )
        )
    )
)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.com • http://cadanalyst.slack.com • http://linkedin.com/in/cadanalyst

Joe Burke

  • Guest
Re: There's got to be a better way
« Reply #4 on: December 01, 2005, 10:36:47 AM »
One other wrinkle if you work ObjectDBX and this is a toolbox function. It may make sense to pass the document as an argument. This way the function isn't limited to the active document.

This version filters out xref layers. but you get my drift.

Code: [Select]
(defun GetLayers ( doc / layers layname laylst )
  (setq layers (vla-get-Layers doc))
  (vlax-for x layers
    (setq layname (vlax-get x 'Name))
    ;filter out xref layers
    (if (not (vl-string-search "|" layname))
      (setq laylst (cons layname laylst))
    )
  )
  (acad_strlsort laylst)
) ;end

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: There's got to be a better way
« Reply #5 on: December 01, 2005, 10:48:19 AM »
If you want the same data via an activex route (including objectdbx) ...

Code: [Select]
(defun ForFun2 ( document / result )
    (vlax-for layer (vla-get-layers document)
        (   (lambda (data)
                (setq result
                    (cons
                        (mapcar
                           '(lambda (key) (cdr (assoc key data)))
                           '(2 62 6)
                        )
                        result
                    )
                )
            )
            (entget (vlax-vla-object->ename layer))
        )   
    )
)

:)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.com • http://cadanalyst.slack.com • http://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: There's got to be a better way
« Reply #6 on: December 01, 2005, 10:59:54 AM »
OT: It's really good to see you posting again Chuck.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.com • http://cadanalyst.slack.com • http://linkedin.com/in/cadanalyst

nivuahc

  • Guest
Re: There's got to be a better way
« Reply #7 on: December 01, 2005, 11:01:33 AM »
OT: It's really good to see you posting again Chuck.

thankee :)

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: There's got to be a better way
« Reply #8 on: December 01, 2005, 11:05:33 AM »
And for completeness ...

Code: [Select]
(defun ForFun3 ( document / result )
    (vlax-for layer (vla-get-layers document)
        (setq result
            (cons
                (mapcar
                   '(lambda (property) (vlax-get layer property))
                   '(name color linetype)
                )
                result
            )
        )
    )
)

:)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.com • http://cadanalyst.slack.com • http://linkedin.com/in/cadanalyst

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: There's got to be a better way
« Reply #9 on: December 02, 2005, 03:30:05 AM »
.. As I said Chuck, depends if you're chasing milliseconds. Yours is still firmly in the running.

160 cycles per second <256 in 1.6> is pretty good.
Code: [Select]
Benchmarking [M.P. 2005] ...........Elapsed milliseconds for 256 iteration(s)/ relative Timing :

    (FORFUN3 KBSG:ACTIVEDOC)..........2113 / 1.4068 <slowest>
    (GETLAYERS_XX KBSG:ACTIVEDOC).....1913 / 1.2736
    (FORFUN)..........................1742 / 1.1598
    (BUILDLAYERLIST)..................1622 / 1.0799
    (BUILDLAYERLIST_JM)...............1512 / 1.0067
    (FORFUN2 KBSG:ACTIVEDOC)..........1502 / 1 <fastest>


This is a variation on the ActiveX method included.
Code: [Select]
(defun GetLayers_xx (document / laylst) 
  (vlax-for each (vla-get-layers document)
    (setq laylst (cons (list (vlax-get each 'Name)
                             (vlax-get each 'Color)
                             (vlax-get each 'LineType)
                       )
                       laylst
                 )
    )
  )
)

PS:
I've excluded Joe's from the test because the functionality is different
« Last Edit: December 02, 2005, 03:45:43 AM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: There's got to be a better way
« Reply #10 on: December 02, 2005, 06:49:43 AM »
... and to put Kerry's comments into perspective ... in a drawing with 1000 layers the delay is imperceptable (~ 60 milliseconds) with the slowest function in the lot; with 10000 layers it's still under 1 second (~ 680 milliseconds). (WXPP, P4, 3GHz, 1 GB RAM).

:)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.com • http://cadanalyst.slack.com • http://linkedin.com/in/cadanalyst

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: There's got to be a better way
« Reply #11 on: December 02, 2005, 08:22:37 AM »
Nice examples of looping & collecting table data.

Thanks Fellas.
I've reached the age where the happy hour is a nap. (°Ώ°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: There's got to be a better way
« Reply #12 on: April 06, 2006, 06:53:36 AM »
Code: [Select]
(defun test6 (i)
 (if (setq i (tblnext "LAYER" (not i)))
  (cons
   (mapcar '(lambda (x) (cdr (assoc x i))) '(2 62 6))
   (test6 t)
  ) ;_  cons
 ) ;_  if
)
Code: [Select]
_$
Benchmarking ...............Elapsed milliseconds / relative speed for 4096 iteration(s):

    (TEST6 nil)..............1047 / 14.45 <fastest>
    (GETLAYERS DOC)..........6969 / 2.17
    (FORFUN2 DOC)............7890 / 1.92
    (BUILDLAYERLIST_JM)......8453 / 1.79
    (BUILDLAYERLIST).........8563 / 1.77
    (FORFUN).................8937 / 1.69
    (GETLAYERS_XX DOC)......14546 / 1.04
    (FORFUN3 DOC)...........15125 / 1 <slowest>

 
_$
« Last Edit: April 06, 2006, 07:36:52 AM by ElpanovEvgeniy »

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: There's got to be a better way
« Reply #13 on: April 06, 2006, 07:39:24 AM »
Code: [Select]
(defun test6 (i)
 (if (setq i (tblnext "LAYER" (not i)))
  (cons
   (mapcar '(lambda (x) (cdr (assoc x i))) '(2 62 6))
   (test6 t)
  ) ;_  cons
 ) ;_  if
)

(test6 nil) vs (test6 t) makes a big difference eh?

:)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.com • http://cadanalyst.slack.com • http://linkedin.com/in/cadanalyst

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: There's got to be a better way
« Reply #14 on: April 06, 2006, 08:22:05 AM »
I apologize, I have made a mistake, wanted it to corrected but have made even more!
Code: [Select]
(defun test7 (i)
 (if (setq i (tblnext "LAYER" i))
  (cons
   (list
     (cdadr i)
     (cdr(cadddr i))
     (cdar(cddddr i))
    ) ;_  mapcar
   (test7 nil)
  ) ;_  cons
 ) ;_  if
)

Code: [Select]
Benchmarking .............Elapsed milliseconds / relative speed for 1024 iteration(s):

    (FORFUN2 DOC)...........1797 / 1.98 <fastest>
    (TEST7 T)...............1937 / 1.84
    (BUILDLAYERLIST_JM).....1984 / 1.8
    (BUILDLAYERLIST)........2000 / 1.78
    (FORFUN)................2094 / 1.7
    (GETLAYERS_XX DOC)......3359 / 1.06
    (FORFUN3 DOC)...........3562 / 1 <slowest>