Author Topic: Selection Set within Selection Set  (Read 5690 times)

0 Members and 1 Guest are viewing this topic.

mailmaverick

  • Bull Frog
  • Posts: 494
Selection Set within Selection Set
« on: March 29, 2014, 09:16:32 AM »
I have a selection set of certain objects (TEXT, LINES etc) in a variable SelSetTotal.

I want to create another selection set (in variable SelSetPart) consisting of all those objects which are present in SelSetTotal and crossing or within the polygon object defined by variable objPolygon.

Note that polygon entity is defined by variable entPolygon and objPolygon is defined as :
Code: [Select]
(setq objPolygon (vlax-ename->vla-object entPolygon))
Please help.

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
Re: Selection Set within Selection Set
« Reply #1 on: March 29, 2014, 11:07:34 AM »
You have 1st sel.set. lets say in variable ss1... Then you can create new sel.set lets say in variable ss2 with
Code: [Select]
(setq ss2 (ssget "_WP" ptlst)) where ptlst is variable containing point lists obtained from your polygon entity
Code: [Select]
(setq ptlst (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= 10 (car x))) (entget polygon))))... Then to obtain common sel.set, you can use this :
Code: [Select]
(setq ss (ACET-SS-INTERSECTION ss1 ss2))
Of course you have to have full ACAD operational (enabled Express Tools (ACET-...) functions extension)
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

mailmaverick

  • Bull Frog
  • Posts: 494
Re: Selection Set within Selection Set
« Reply #2 on: March 29, 2014, 11:21:01 AM »
Thanks Ribar. You are always of great help.

Just for knowledge, is there any other way of doing so without ACET- functions ?



Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Selection Set within Selection Set
« Reply #3 on: March 29, 2014, 12:18:20 PM »
Marco,
From the OP
Quote
consisting of all those objects which are present in SelSetTotal and crossing or within the polygon object defined by variable objPolygon.

The operative word in the conditional was OR. I believe a union of ss items is required, not an in intersection.

mailmaverick,
Please confirm you want
A) A combination of both selection Sets.
or
b) A Selection of common entities. ( ie occurring only in both original selection sets.)
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.

mailmaverick

  • Bull Frog
  • Posts: 494
Re: Selection Set within Selection Set
« Reply #4 on: March 29, 2014, 12:53:42 PM »
Dear Kerry,

I want Selection of common entities. ( i.e. occurring only in both original selection sets.)

Thanks.

Lee Mac

  • Seagull
  • Posts: 12906
  • London, England
Re: Selection Set within Selection Set
« Reply #5 on: March 29, 2014, 02:21:19 PM »
If I've correctly understood what you are looking to achieve, two separate selection sets should not be required since you can include a filter for the required Text & Line objects when retrieving a selection set of all objects residing within the Window Polygon.

Here is a quick example:
Code: [Select]
(defun c:test ( / app ent enx lst sel )
    (if
        (and
            (setq ent (car (entsel "\nSelect polyline: ")))
            (= "LWPOLYLINE" (cdr (assoc 0 (setq enx (entget ent)))))
        )
        (progn
            (setq app (vlax-get-acad-object)
                  lst (mapcar '(lambda ( x ) (trans (cdr x) ent 0)) (vl-remove-if-not '(lambda ( x ) (= 10 (car x))) enx))
            )
            (vla-zoomwindow app
                (vlax-3d-point (apply 'mapcar (cons 'min lst)))
                (vlax-3d-point (apply 'mapcar (cons 'max lst)))
            )
            (setq sel
                (ssget "_WP" (mapcar '(lambda ( x ) (trans x 0 1)) lst)
                   '(
                        (0 . "TEXT,LINE")
                    )
                )
            )
            (vla-zoomprevious app)
            (sssetfirst nil sel)
        )
    )
    (princ)
)
(vl-load-com) (princ)

Note that a temporary zoom is required since the graphical ssget mode strings (e.g. Window / Crossing / Polygon) will only select objects visible in the drawing area at the time of selection.

( ssget function reference )

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Selection Set within Selection Set
« Reply #6 on: March 29, 2014, 02:49:57 PM »
Have a play with these library functions to do your selection set manipulation.

Murphy's Law says that the selections will be made at different times ....

Code - Auto/Visual Lisp: [Select]
  1.  
  2.  
  3. ;;;------------------------------------------------------------------
  4. ;;;------------------------------------------------------------------
  5. ;;;
  6. ;; Union of two selection sets and returns common elements
  7. (defun kdub:ssintersect (ss1 ss2 / ss l1 l2)
  8.   (setq ss (ssadd))
  9.   (cond
  10.     ((and ss1 ss2)
  11.      (setq l1 (kdub:ss->entlist ss1)
  12.            l2 (kdub:ss->entlist ss2)
  13.      )
  14.      (foreach x (vl-remove-if-not '(lambda (x) (member x l2)) l1) (ssadd x ss))
  15.     )
  16.     (t (setq ss nil))
  17.   )
  18.   ss
  19. )
  20.  
  21. ;;;------------------------------------------------------------------
  22. ;;;------------------------------------------------------------------
  23. ;;;
  24. ;; Subtracts one selection set from another and returns their difference
  25. ;; NOT optimal because it changes the previous/last selection set.
  26. (defun kdub:sssubtract (ss1 ss2 / ss)
  27.   (cond ((and ss1 ss2)
  28.          (vl-cmdf "._Select" ss1 "_Remove" ss2 "")
  29.          (setq ss (ssget "_P"))
  30.         )
  31.         (ss1 (setq ss ss1))
  32.         (t (setq ss nil))
  33.   )
  34.   ss
  35. )
  36.  
  37. ;;;------------------------------------------------------------------
  38. ;;;------------------------------------------------------------------
  39. ;;;
  40. ;;; Union of two selection sets
  41.  
  42. (defun kdub:ssunion (ss1 ss2 / ss index)
  43.   (setq ss (ssadd))
  44.   (cond ((and ss1 ss2)
  45.          (setq index -1)
  46.          (repeat (sslength ss1) (ssadd (ssname ss1 (setq index (1+ index))) ss))
  47.          (setq index -1)
  48.          (repeat (sslength ss2) (ssadd (ssname ss2 (setq index (1+ index))) ss))
  49.         )
  50.         (ss1 (setq ss ss1))
  51.         (ss2 (setq ss ss2))
  52.         (t (setq ss nil))
  53.   )
  54.   ss
  55. )
  56.  
  57. ;;;------------------------------------------------------------------
  58. ;;;------------------------------------------------------------------
  59. ;;;
  60. (defun kdub:ss->entlist (ss / i returnval)
  61.   (if (and ss (< 0 (sslength ss)))
  62.     (setq returnval (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))
  63.   )
  64.   returnval
  65. )
  66. ;;;------------------------------------------------------------------
  67. ;;;------------------------------------------------------------------
  68. ;;;
  69.  
  70.  

Test routines

Code - Auto/Visual Lisp: [Select]
  1. (setq ss1 (ssget))
  2. (setq ss2 (ssget))
  3.  
  4.  
  5. (setq ssu1 (kdub:ssunion ss1 ss2))
  6. (setq ssu2 (kdub:ssunion ss1 nil))
  7. (setq ssu3 (kdub:ssunion nil ss2))
  8. (setq ssu4 (kdub:ssunion nil nil))
  9.  
  10.  
  11. (setq ss5 (kdub:ssintersect ss1 ss2))
  12. (setq ss6 (kdub:ssintersect ss1 nil))
  13.  
« Last Edit: March 29, 2014, 03:11:48 PM by 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.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Selection Set within Selection Set
« Reply #7 on: March 29, 2014, 03:03:50 PM »

and a piccy

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.

mailmaverick

  • Bull Frog
  • Posts: 494
Re: Selection Set within Selection Set
« Reply #8 on: April 03, 2014, 11:10:56 AM »
I calculated the time taken for intersection of selection sets with two functions :-

1.) (setq ss (ACET-SS-INTERSECTION ss1 ss2))

2.) (setq ss (kdub:ssintersect ss1 ss2))

and found stark contrast in the time taken.

My code :

Code: [Select]

(defun c:test ()
  (setq ss1 (ssget "_:L"))
  (setq ss2 (ssget "_:L"))
  (setq Start (getvar "Millisecs"))
  (repeat 250 (setq ss (ACET-SS-INTERSECTION ss1 ss2)))
  (setq End (getvar "Millisecs"))
  (setq yu (- End Start))
  (setq yu (/ yu 1000.00))
  (princ "\nTime Taken to Run in ACET Method : ")
  (princ yu)
  (princ " seconds \n")
  (setq Start (getvar "Millisecs"))
  (repeat 250 (setq ss (kdub:ssintersect ss1 ss2)))
  (setq End (getvar "Millisecs"))
  (setq yu (- End Start))
  (setq yu (/ yu 1000.00))
  (princ "\nTime Taken to Run in KDUB Method : ")
  (princ yu)
  (princ " seconds \n")
  (princ)
)


(defun kdub:ssintersect (ss1 ss2 / ss l1 l2)
  (setq ss (ssadd))
  (cond ((and ss1 ss2)
(setq l1 (kdub:ss->entlist ss1)
       l2 (kdub:ss->entlist ss2)
)
(foreach x (vl-remove-if-not '(lambda (x) (member x l2)) l1)
   (ssadd x ss)
)
)
(t (setq ss nil))
  )
  ss
)

(defun kdub:ss->entlist (ss / i returnval)
  (if (and ss (< 0 (sslength ss)))
    (setq returnval (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))
  )
  returnval
)


Results :

Time Taken to Run in ACET Method : 2.792 seconds

Time Taken to Run in KDUB Method : 293.407 seconds


Why is so much difference in time taken ? Or, why is ACET function so fast ?

Also, my other query, are all ACET functions so fast than our normal routines ? If yes, then why ?

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Selection Set within Selection Set
« Reply #9 on: April 03, 2014, 03:46:06 PM »

These are my times

Quote
Select objects: Specify opposite corner: 364 found

Time Taken to Run in ACET Method : 2.527 seconds

Time Taken to Run in KDUB Method : 5.102 seconds

Note: Add a (gc) for garbage collection immediately before each assignment to Start
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.

ymg

  • Guest
Re: Selection Set within Selection Set
« Reply #10 on: April 03, 2014, 04:03:02 PM »
The ACET function are pre-compiled this is where
you get the difference.

If you do compile Kerry's function they may end up being faster.

ymg

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Selection Set within Selection Set
« Reply #11 on: April 03, 2014, 04:18:49 PM »
Even without compiling, this is faster

Code - Auto/Visual Lisp: [Select]
  1.  
  2. (defun kdub:ssintersect2 (ss1 ss2 / ss tmp index)
  3.   (setq ss (ssadd))
  4.   (cond ((and ss1 ss2)
  5.          (setq index -1)
  6.          (repeat (sslength ss1)
  7.            (if (ssmemb (setq tmp (ssname ss1 (setq index (1+ index)))) ss2)
  8.              (ssadd tmp ss)
  9.            )
  10.          )
  11.         )
  12.         (t (setq ss nil))
  13.   )
  14.   ss
  15. )
  16.  
  17.  

Code - Auto/Visual Lisp: [Select]
  1.   (setq ss1 (ssget "_:L"))
  2.   (setq ss2 (ssget "_:L"))
  3.  
  4. (benchmark '((kdub:ssintersect ss1 ss2)
  5.              (kdub:ssintersect2 ss1 ss2)
  6.              (ACET-SS-INTERSECTION ss1 ss2)
  7.             )
  8. )

Quote
; 1 form loaded from #<editor "K:/TestForum/ss stuff.LSP">
_$
Benchmarking [M.P. 2005 < revised kdub 2005>] ........
Elapsed milliseconds for 32 iteration(s)/ relative Timing :

    (KDUB:SSINTERSECT SS1 SS2).........686 / 2.0000 <slowest>
    (ACET-SS-INTERSECTION SS1 SS2).....390 / 1.1370
    (KDUB:SSINTERSECT2 SS1 SS2)........343 / 1.0000 <fastest>

just a bit of cat skinning .. :)
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.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Selection Set within Selection Set
« Reply #12 on: April 03, 2014, 04:36:11 PM »

Further testing indicates that the result timing depends on the relative composition of the selection sets.

 disparate timing is returned from selection sets comprising :-

Significantly different sizes.
Large sets with very few common elements.
Order of parameters when sets are different sizes.

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.

Lee Mac

  • Seagull
  • Posts: 12906
  • London, England
Re: Selection Set within Selection Set
« Reply #13 on: April 03, 2014, 06:02:16 PM »
You might be able to squeeze out a little extra performance by only iterating over the smallest set, e.g.:

Code - Auto/Visual Lisp: [Select]
  1. (defun ssintersect ( ss1 ss2 / ent idx rtn )
  2.     (setq rtn (ssadd))
  3.     (if (< (sslength ss2) (sslength ss1))
  4.         (mapcar 'set '(ss1 ss2) (list ss2 ss1))
  5.     )
  6.     (repeat (setq idx (sslength ss1))
  7.         (if (ssmemb (setq ent (ssname ss1 (setq idx (1- idx)))) ss2)
  8.             (ssadd ent rtn)
  9.         )
  10.     )
  11.     rtn
  12. )

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Selection Set within Selection Set
« Reply #14 on: April 03, 2014, 06:08:54 PM »
You might be able to squeeze out a little extra performance by only iterating over the smallest set, e.g.:


Yes that is correct, I have several versions which all slightly improve the performance of the original.

added:
Perhaps not surprisingly, my code for that algorithm is essentially exactly the same as the code you posted..
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.