Author Topic: select all touching entities  (Read 6136 times)

0 Members and 1 Guest are viewing this topic.

hmspe

  • Bull Frog
  • Posts: 362
select all touching entities
« on: March 18, 2008, 10:38:46 AM »
As part of a larger project I need to have a routine similar to fastsel.lsp that will get a selection set of lines, lwplines, circles, arcs, splines, and ellipses that touch an entity I select or that touch one of the touching entities.  The routine has to run in R2004 and newer.  I'd like to avoid using fastsel.lsp if possible (express tools could go away at any time).  Before I spend a couple of days coding I thought I'd ask if anyone either has a routine they'd be willing to share or has any tips on best approach. 

The two approaches I'm considering at this point are (1) select the first entity, offset both directions, convert offsets to plines, combine plines into a closed pline, use ssget "CP", then iterate through the resulting selection set.  Closed entities would be split in half and ssget would be run on each half.  (2) get a selection set of all lines, lwplines, etc. on screen, then iterate through the selection set with "intersectwith" to build a set of entities touching the selected entity, then loop until the entire mesh is selected.  Any thoughts on which is better for a general function would be welcome.

Thanks in advance,

Martin
"Science is the belief in the ignorance of experts." - Richard Feynman

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: select all touching entities
« Reply #1 on: March 18, 2008, 10:48:17 AM »
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.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: select all touching entities
« Reply #2 on: March 18, 2008, 11:08:37 AM »
  Here is a subroutine I created for my BreakAll.lsp. It may be useful to you.
Code: [Select]
  ;;===========================================================================
  ;;  get all objects touching entities in the sscross                         
  ;;  limited obj types to "LINE,ARC,SPLINE,LWPOLYLINE,POLYLINE,CIRCLE,ELLIPSE"
  ;;===========================================================================
  (defun gettouching (sscros / ss lst lstb lstc objl)
    (and
      (setq lstb (vl-remove-if 'listp (mapcar 'cadr (ssnamex sscros)))
            objl (mapcar 'vlax-ename->vla-object lstb)
      )
      (setq
        ss (ssget "_A" (list (cons 0 "LINE,ARC,SPLINE,LWPOLYLINE,POLYLINE,CIRCLE,ELLIPSE")
                             (cons 410 (getvar "ctab"))))
      )
      (setq lst (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))
      (setq lst (mapcar 'vlax-ename->vla-object lst))
      (mapcar
        '(lambda (x)
           (mapcar
             '(lambda (y)
                (if (not
                      (vl-catch-all-error-p
                        (vl-catch-all-apply
                          '(lambda ()
                             (vlax-safearray->list
                               (vlax-variant-value
                                 (vla-intersectwith y x acextendnone)
                               ))))))
                  (setq lstc (cons (vlax-vla-object->ename x) lstc))
                )
              ) objl)
         ) lst)
    )
    lstc
  )
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.

hmspe

  • Bull Frog
  • Posts: 362
Re: select all touching entities
« Reply #3 on: March 18, 2008, 01:32:12 PM »
CAB,

Thanks for the quick replies.  I played with SMadsen's routine last night, but was concerned with the size of the selection window, which is the bounding box for the selected entity.  I had looked through your BreakAll.lsp, but had overlooked the gettouching function.

My mindset last night was that fastsel's approach of essentially using a selection window for each entity that's barely bigger than the entity would give the fastest routine because there would be no need to check for intersections.  This morning I'm not so sure.  It may be that checking for intersections against either the entities in a bounding box or all lines, arcs, etc., would be faster than creating all the geometry to emulate fastsel.  Time for testing....

Martin

     
"Science is the belief in the ignorance of experts." - Richard Feynman

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: select all touching entities
« Reply #4 on: March 18, 2008, 04:52:12 PM »
Something to play with.
Code: [Select]
;;===========================================================================
;;  get all objects touching entities in the sscross and touching each other
;;  limited obj types to "LINE,ARC,SPLINE,LWPOLYLINE,POLYLINE,CIRCLE,ELLIPSE"
;;===========================================================================
(defun GetAllTouching (sscros / ss lst1 2test
       ss->olist GetTouching )
  ;;  selection set to list of vla objects
  (defun ss->olist (ss / lst i ename)
    (setq i -1)
    (while (setq ename (ssname ss (setq i (1+ i))))
      (setq lst (cons (vlax-ename->vla-object ename) lst))
    )
    lst
  )

  ;;  return a list of objects in list2 that touch objects in list1
  (defun GetTouching (ol1 ol2 / touching)
    (mapcar
      (function
(lambda (x)
  (mapcar
    (function
      (lambda (y)
(if (not
      (vl-catch-all-error-p
(vl-catch-all-apply
  '(lambda ()
     (vlax-safearray->list
       (vlax-variant-value
(vla-intersectwith y x acextendnone)
       )
     )
   )
)
      )
    )
  (setq touching (cons x touching))
)
      )
    )
    ol1
  )
)
      )
      ol2
    )
    touching
  )

  (and
    (setq 2test (ss->olist sscros))
    ;;  ignore objects on frozen layers
    (setq ss
       (ssget "_A"
(list
   (cons 0 "LINE,ARC,SPLINE,LWPOLYLINE,POLYLINE,CIRCLE,ELLIPSE")
   (cons 410 (getvar "ctab"))
)
       )
    )
    (setq ObjectsInCurrentSpace (ss->olist ss))
    (setq lst1 2test)
    (while
      (and
(setq ObjectsInCurrentSpace
       (vl-remove-if '(lambda (x) (vl-position x 2test)) ObjectsInCurrentSpace)
)
(setq 2test (GetTouching 2test ObjectsInCurrentSpace))
(setq lst1 (append 2test lst1))
      )
    )
  )
  lst1
)




Code: [Select]
(defun c:test (/ ss1 touching)
  (and
    (setq ss1 (ssget))
    (setq touching (GetAllTouching ss1))
    (mapcar '(lambda (x)
       (vla-Highlight x :vlax-true)
       (vla-update x)
     )
    touching
    )
    (getstring "\nPress Enter to continue.")
    (command "regen")
  )
  (princ)
)
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.

VovKa

  • Water Moccasin
  • Posts: 1631
  • Ukraine
Re: select all touching entities
« Reply #5 on: March 18, 2008, 06:08:41 PM »
why not use Fence selection (ssget "_F")?

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: select all touching entities
« Reply #6 on: March 18, 2008, 06:17:39 PM »
If I understand the request, he wants objects touching the selected object AND objects that touch those objects.
Sort of a chain of overlapping objects.

You could use Fence selection as long as you were satisfied with the resolution on curved objects.
« Last Edit: March 18, 2008, 06:23:46 PM by CAB »
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.

VovKa

  • Water Moccasin
  • Posts: 1631
  • Ukraine
Re: select all touching entities
« Reply #7 on: March 18, 2008, 06:35:07 PM »
aha, now I got the point, sorry.

hmspe

  • Bull Frog
  • Posts: 362
Re: select all touching entities
« Reply #8 on: March 19, 2008, 11:36:44 PM »
CAB,

Correct on what I'm trying to do.  The initial purpose is getting a selection set to pass to the boundary command in a routine that centers the text in cells in equipment schedules.  Also on the list is creating a selection set to pass to overkill as a step in cleaning up drawings.

Thanks for the test routine.  I wish my code was as elegant.  It gave me a way to test options, which tests did not come out quite like I expected.  I used a partial floor plan as a test drawing.  Fastsel reported 171 touching entities out of 300.  I added timers that start after the seed entity is selected and stops as soon as the entity list is complete.  The fastsel was modified so that it always gets the complete mesh.  I also did a bit of cleanup as I was going through annotating the code while trying to figure out how it works, things like making the local variables unique in each defun.  Running on my laptop the alltouch routine took 48.015994 seconds, 47.969002, and 48.421986 seconds on three runs.  The edited fastsel routine took 0.547010 seconds, 0.484005 seconds, and 0.484005 seconds on three runs.  As a next step I plan to embed all the express tools functions into the edited fastsel so the routine isn't dependent on having express tools available, in case they go away in future versions.   

Martin
"Science is the belief in the ignorance of experts." - Richard Feynman

uncoolperson

  • Guest
Re: select all touching entities
« Reply #9 on: March 20, 2008, 12:42:11 AM »
who did the ghosting routines here at the swamp? [mp did]
mine did, but it required a bunch of exploding... which wasn't nearly as nice

couldn't you use the begining of that to:

psuedo code

convert everything to vectors (in code)
selection set cp on each individual vector
convert that selection set to vectors (in code)
selection set cp on each individual vector

remove duplicates and combine selection sets


function name idea..... six_degrees_of_seperation
« Last Edit: March 20, 2008, 12:55:54 AM by uncoolperson »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: select all touching entities
« Reply #10 on: March 20, 2008, 09:01:19 AM »
Yes, Fastsel is very quick. It looks like it uses
(setq ss (ssget "_f" (nth n lst3) flt));setq
to get the On Screen objects.
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.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: select all touching entities
« Reply #11 on: March 20, 2008, 09:04:59 AM »
CAB,

Correct on what I'm trying to do.  The initial purpose is getting a selection set to pass to the boundary command in a routine that centers the text in cells in equipment schedules. 
Perhaps if you posted a sample of the text cells in a DWG we could get a better idea for the solution.
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.

hmspe

  • Bull Frog
  • Posts: 362
Re: select all touching entities
« Reply #12 on: March 20, 2008, 12:11:36 PM »
CAB,

I've attached a sample drawing that has a sample schedule that I receive and what I clean it up to.  I'm trying to automate as much of the process as possible.  I have a routine that centers the text.  It uses the boundary command to get the centroid of each cell and to create a pline so that the routine can determine what text is in each cell.  The routine allows any text selection method, including picking one text entity to center just one cell's text.   

Four ways being able to get a ss of all touching line work will help:
  1.  the ss can be passed to flatten
  2.  get the flattened ss, then pass to overkill
  3.  get the overkill'd ss and pass to gap.lsp or something similar which will either highlight faulty intersections or correct faulty intersections.
  4.  the boundary command can be constrained to a set of entities, which might speed things up a bit on large schedules.

The drawing also includes the partial floor plan I was using in the timed tests.

I haven't fully analyzed fastsel, but from what I can tell fastsel essentially does an offset to each side of each entity, then does (ssget "_f" ... based on the offsets so there's a fuzz factor.  The offset distance is based on pixel size. 

Thanks for your help.

Martin
"Science is the belief in the ignorance of experts." - Richard Feynman