Author Topic: Merge two selection sets  (Read 6754 times)

0 Members and 1 Guest are viewing this topic.

Lupo76

  • Bull Frog
  • Posts: 343
Merge two selection sets
« on: April 19, 2012, 05:37:56 AM »
Hello everyone,
I created the following function to merge two sets of selection:

Code: [Select]
(defun ssgetunion (sel2 sel1 /)
  (if sel1
    (if sel2
      (progn
        (setq ct 0)
        (repeat (sslength sel2)
          (ssadd (ssname sel2 ct) sel1)
          (setq ct (1+ ct))
        )
      )
      sel1
    )
    (princ "\nNIL.")
  )
  sel1
)

Unfortunately, when the selection sets contain many objects is slow.  :-(
Any suggestions to make quickly a selection set from two distinct selection sets?
Thanks in advance

Lee Mac

  • Seagull
  • Posts: 12915
  • London, England
Re: Merge two selection sets
« Reply #1 on: April 19, 2012, 06:10:10 AM »
Maybe only iterate over the smallest set?

Code - Auto/Visual Lisp: [Select]
  1. (defun ss-union ( s1 s2 / si )
  2.     (cond
  3.         (   (null s1) s2)
  4.         (   (null s2) s1)
  5.         (   (< (sslength s1) (sslength s2))
  6.             (repeat (setq si (sslength s1))
  7.                 (ssadd (ssname s1 (setq si (1- si))) s2)
  8.             )
  9.             s2
  10.         )
  11.         (   t
  12.             (repeat (setq si (sslength s2))
  13.                 (ssadd (ssname s2 (setq si (1- si))) s1)
  14.             )
  15.             s1
  16.         )
  17.     )
  18. )

There is also the Express Tools' acet-ss-union function to consider.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Merge two selection sets
« Reply #2 on: April 19, 2012, 08:00:15 AM »
Sounds a lot like this thread: http://forums.augi.com/showthread.php?138426-sel-sets-subfunctions

Strange how similar stuff keeps poping up in batches! It seems it's some kind of un-conscious "telepathy" across the global population  ;)
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Lupo76

  • Bull Frog
  • Posts: 343
Re: Merge two selection sets
« Reply #3 on: April 20, 2012, 01:37:31 AM »
Thank you all for your responses!

Stefan

  • Bull Frog
  • Posts: 319
  • The most I miss IRL is the Undo button
Re: Merge two selection sets
« Reply #4 on: April 20, 2012, 05:50:37 AM »
Just an alternative, using SelectionSets collection.
The result is a SelectionSet as a vla-object
Code - Auto/Visual Lisp: [Select]
  1. (defun union_ss (ss1 ss2 / vla-object ssets ss3)
  2.  
  3.   (defun vla-object (x) (if (= (type x) 'ENAME) (vlax-ename->vla-object x)))
  4.  
  5.   (vl-catch-all-apply 'vla-Add (list (setq ssets (vla-get-SelectionSets (vla-get-ActiveDocument (vlax-get-acad-object)))) "temp_name_selection_set"))
  6.   (vl-catch-all-apply 'vla-Clear (list (setq ss3 (vla-item ssets "temp_name_selection_set"))))
  7.   (mapcar
  8.     (function
  9.       (lambda (ss)
  10.         (vla-AddItems
  11.           ss3
  12.           (vlax-safearray-fill
  13.             (vlax-make-safearray
  14.               vlax-vbObject
  15.               (cons 0 (1- (sslength ss)))
  16.             )
  17.             (vl-remove
  18.               nil
  19.               (mapcar
  20.                 (function
  21.                   (lambda (x)
  22.                     (vla-object (cadr x))
  23.                   )
  24.                 )
  25.                 (ssnamex ss)
  26.               )
  27.             )
  28.           )
  29.         )
  30.       )
  31.     )
  32.     (list ss1 ss2)
  33.   )
  34.   ss3
  35. )
And the test function
Code - Auto/Visual Lisp: [Select]
  1. (defun C:TEST ( / ss1 ss2)
  2.   (if
  3.     (and
  4.       (princ "\n  ***  First selection set  ***")
  5.       (setq ss1 (ssget))
  6.       (princ "\n  ***  Second selection set  ***")
  7.       (setq ss2 (ssget))
  8.     )
  9.     (union_ss ss1 ss2)
  10.   )
  11. )

taner

  • Guest
Re: Merge two selection sets
« Reply #5 on: April 20, 2012, 05:56:29 AM »
Code - Auto/Visual Lisp: [Select]
  1. (defun ssunion (ss1 ss2)
  2.   (cond
  3.     ((and
  4.        (> (sslength ss1) 0)
  5.        (> (sslength ss2) 0)
  6.      )
  7.      (vl-cmdf "._select" ss1 ss2 "")
  8.      (ssget "_P")
  9.     )
  10.     ((or
  11.        (not ss2)
  12.        (= (sslength ss2) 0)
  13.      )
  14.      ss1
  15.     )
  16.     ((or
  17.        (not ss1)
  18.        (= (sslength ss1) 0)
  19.      )
  20.      ss2
  21.     )
  22.   )
  23. )
  24.  
  25. (defun sslst-union (sslist / ss)
  26.   (setq ss (ssadd))
  27.   (mapcar
  28.     '(lambda (x / c)
  29.        (setq c -1)
  30.        (repeat (sslength x)
  31.          (ssadd (ssname x (setq c (1+ c))) ss)
  32.        )
  33.      )
  34.     sslist
  35.   )
  36.   (if(> (sslength ss) 0) ss nil)
  37. )

edit:kdub -> code = cadlisp-7
« Last Edit: April 20, 2012, 08:06:56 AM by Kerry »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Merge two selection sets
« Reply #6 on: April 20, 2012, 07:48:10 AM »
This

Code - Auto/Visual Lisp: [Select]
  1.     ((and
  2.        (> (sslength ss1) 0)
  3.        (> (sslength ss2) 0)
  4.      )
  5.  

should be this

Code - Auto/Visual Lisp: [Select]
  1.    
  2.  
  3.     ((and
  4.        ss1
  5.        ss2
  6.      )
  7.  

evaluating a selection set will return either the set or nil.

if the set is empty ( nil )
then
(sslength ss1)
will cause an error  < error: bad argument type: lselsetp nil >

Regards
Kerry
 
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.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Merge two selection sets
« Reply #7 on: April 20, 2012, 07:55:45 AM »
Good point Kerry. And nice code Tsec2nd. That one's definitely going to be the fastest. The only time it's not going to work is if some of the items inside the original selection sets are on a different tab / space / nested / etc. Other than that it's quite good.

For the others it's difficult to say what the fastest one would be. Lee's is modifying one of the original sets. Stefan's is creating a named selection set (the same name every time) - if this is recreated each time from a blank selection set, thus it errors on every pass after the 1st time it's used.

Trying to do a benchmark gets affected by Lee's in all instances - making the rest of the test inaccurate, since it only runs once then never adds to a selection set again (just runs through). This is a similar problem as in the link I've posted to the AUGI thread, RenderMan's also modifies one of the original selection sets.

All 3 of these appear around 8 times slower than Tsec2nd's.

Lupo's seems to be 32 times slower, but has the same problem with modifying the original set.

Anyhow, my ss-union2 (from the AUGI thread) is 10 times slower than Tsec2nd's (the only 2 I can reliably test). It creates a 3rd selection set every time (thus the originals are left as is) and can handle entities on different layouts. I'm not saying it's better, just that if speed is less important than being able to get at all entities you may need to go with this instead.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Merge two selection sets
« Reply #8 on: April 20, 2012, 08:12:08 AM »
Actually, re-going through Stefan's code: his is accommodating the error and returns a cleared and re-added selection set. The only hassle I can note is if you use his twice and then use the returned 2 selection sets in one go - very seldom that you'd want to do this (at least AFAICT). Though: what do you do with the vla selection set? You can't send it to a command can you?
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Stefan

  • Bull Frog
  • Posts: 319
  • The most I miss IRL is the Undo button
Re: Merge two selection sets
« Reply #9 on: April 20, 2012, 09:09:28 AM »
...Though: what do you do with the vla selection set? You can't send it to a command can you?
A few examples of using collections:
Code - Auto/Visual Lisp: [Select]
  1. (vlax-for x vla_ss (vla-Move x (vlax-3d-point '(0 0 0)) (vlax-3d-point '(1000 1000 1000))))
  2. (vlax-for x vla_ss (vla-put-color x acRed))
First, I did try Visual Lisp way to see if I can speed up the process. But it cant be faster because it iterate each of selections set, not only one.

...The only hassle I can note is if you use his twice and then use the returned 2 selection sets in one go - very seldom that you'd want to do this (at least AFAICT). ...
Now, I wonder why someone would want to union two selections after all?
To process multiple selections, this can be used:
Code - Auto/Visual Lisp: [Select]
  1.     (lambda (ss)
  2.       (repeat (setq i (sslength ss))
  3.         (vla-put-Color
  4.           (vlax-ename->vla-object (ssname ss (setq i (1- i))))
  5.           acRed
  6.           )
  7.         )
  8.       )
  9.     )
  10.   (list ss1 ss2)
  11.   )
Multiple selections can be passed to a function like this:
Code - Auto/Visual Lisp: [Select]
  1. (command "_chprop" ss1 ss2 "" "c" 1 "")

David Bethel

  • Swamp Rat
  • Posts: 656
Re: Merge two selection sets
« Reply #10 on: April 20, 2012, 10:00:16 AM »
I was thinking of making a list of all the enames in the picksets as a ssget filter

Just testing a bit and I found that this doesn't work

Where (entlast) is not nil:

Code: [Select]
(setq ss (ssget "X" (list (cons -1 (entlast)))))


Or am I missing something.....

-David
R12 Dos - A2K

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Merge two selection sets
« Reply #11 on: April 20, 2012, 10:03:35 AM »
Yep, you're correct Stephan. I did note that it's an extremely unlikely situation. And your sample does show that you don't need to union 2 selectionsets in order to pass them to a command (kudos!), the only place I can think of using this is in something like that move operation.

If you want to use the vla-Move (or some such thing), then Stefan's would work best for you. If you have to use an entmod to do this, then you'd need one of the AutoLisp versions (say you're on Mac or using BricsCAD on Linux, i.e. no ActiveX available). Or you could simply send both selection sets to the move (copy, rotate, etc.) command  ;) ... i.e. let acad itself handle those unions.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Merge two selection sets
« Reply #12 on: April 20, 2012, 10:05:55 AM »
I was thinking of making a list of all the enames in the picksets as a ssget filter
The idea might work, but I think you might rather want to use the Handle. Filters don't seem to work well with enames. Though in that case I think it's going to be slower, as you'd have the entget / vla-get-Handle each entity in the selection sets - then strcat that into a string for creating '((5 . "Handle1,Handle2,...HandleN")).
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.