Jump to content

select within a polyline containing arcs and splines


supercell

Recommended Posts

Hi,

I am trying to find a lisp routine that will allow me to use pick multiple closed polylines and use them to create a selection set of objects within them. There are a few routines out there but none of them handle arcs, ellipses or splines.

 

Here is an old thread form 2007 and wondered if anyone had found the time to progress it.

 

http://www.cadtutor.net/forum/showthread.php?11682-Selecting-objects-within-a-polyline&highlight=select+polyline

 

I would appreciate any guidance someone can offer. Just to clarify, I cannot program. Appreciate any time you can give to this one.

 

Many thanks in advance.

Rick

Edited by supercell
Link to comment
Share on other sites

Try this ....

 

(if (setq adds (ssadd)
         ss   (ssget '((0 . "*POLYLINE") (-4 . "&=") (70 . 1)))
   )
 (repeat (setq i (sslength ss))
   (foreach p (entget (ssname ss (setq i (1- i))))
     (if (eq (car p) 10)
       (setq l (cons (list (cadr p) (caddr p)) l))
     )
   )
   (if (setq s (ssget "_WP" l))
     (repeat (setq in (sslength s)) (ssadd (ssname s (setq in (1- in))) adds))
   )
   (setq l nil)
 )
)
(sssetfirst nil adds)

Link to comment
Share on other sites

@Tharwat: At first I was thinking the same, but after checked the previous thread linked by OP, I believe that he/she is looking in fact for a more advanced solution, one that allow usage of polylines with arc segments, and probably of ellipses and closed splines. It will be very useful to have an example drawing.

Link to comment
Share on other sites

Very simple method:

 

(defun selectinside ( ent acc / i j l )
   (setq i (/ (vlax-curve-getdistatparam ent (vlax-curve-getendparam ent)) acc)
         j (- i)
   )
   (repeat (fix acc)
       (setq l (cons (trans (vlax-curve-getpointatdist ent (setq j (+ j i))) 0 1) l))
   )
   (ssget "_WP" l)
)

Test function:

 

(defun c:test ( / e )
   (if
       (and
           (setq e (car (entsel)))
           (member (cdr (assoc 0 (entget e))) '("CIRCLE" "ELLIPSE" "SPLINE" "LWPOLYLINE" "POLYLINE"))
       )
       (sssetfirst nil (selectinside e 100))
   )
   (princ)
)
(vl-load-com) (princ)

Otherwise, use my Entity to Point List function to approximate the object by a point list.

  • Like 1
Link to comment
Share on other sites

Wow.

 

It never ceases to amaze me what you guys can do with so few lines of code. Very elegant. Or should i say it looks very elegant if i knew how it all worked. Suffice to say it does work on polylines arcs circles and splines. Thank you all for the very prompt responses. I have signed and and will try to help out the beginners with what i can. I guess that is what it is all about.

 

Thanks

Rick

Link to comment
Share on other sites

One other thing. Is it possible to use this routine as a transparent command using the an apostrophe. I had a go but it didn't seem to work. I would like to use it whilst making a block.

 

Thanks again.

Link to comment
Share on other sites

Just call Lee's command and after create the selection set of items you want to build the block from, call the BLOCK command. Please ensure that PICKFIRST system variable is set to 1.

Link to comment
Share on other sites

To use the selection tool transparently, you need to adjust a little the code to ensure that return what is expected:

(defun c:test ( / e )
   (if
       (and
           (setq e (car (entsel)))
           (member (cdr (assoc 0 (entget e))) '("CIRCLE" "ELLIPSE" "SPLINE" "LWPOLYLINE" "POLYLINE"))
       )
[color=magenta]     (selectinside e 100)[/color]
[color=magenta]     (princ)[/color]
   )
)

Link to comment
Share on other sites

Furthermore, you can adjust the code to use it both as Lee intended and transparently.

(defun c:test ( / e )
   (if (and
           (setq e (car (entsel)))
           (member (cdr (assoc 0 (entget e))) '("CIRCLE" "ELLIPSE" "SPLINE" "LWPOLYLINE" "POLYLINE"))
       )
[color=magenta]     (if (= (getvar "CMDACTIVE") 0)
     (sssetfirst nil (selectinside e 100))
     (selectinside e 100)
    )
    (princ)
[/color]    )
)

Link to comment
Share on other sites

(vl-load-com)
(defun SelectByEntity  (entity mode accuracy / points delta index)
 (setq delta (/ (vlax-curve-GetDistAtParam entity (vlax-curve-GetEndParam entity))
                accuracy)
       index (- delta))
 (ssget mode
        (repeat (fix accuracy)
          (setq points
                 (cons (trans
                         (vlax-curve-GetPointAtDist entity (setq index (+ index delta)))
                         0
                         1)
                       points)))))

(setq *SelectByEntity* '("_WP" . 100.0))
(defun c:SelectByEntity  (/ entity)
 (while
   (not (listp (setq entity (progn (prompt (strcat "\nMode="
                                                   (car *SelectByEntity*)
                                                   "; Accuracy="
                                                   (rtos (cdr *SelectByEntity*))))
                                   (initget "Mode Accuracy")
                                   (entsel "Pick surrounding entity [Mode/Accuracy]: ")))))
    (cond
      ((eq entity "Mode")
       (initget "WP CP F")
       (if (setq entity (getkword "Mode [WP/CP/F]: "))
         (setq *SelectByEntity* (cons (strcat "_" entity) (cdr *SelectByEntity*)))))
      ((eq entity "Accuracy")
       (if (setq entity (getdist "\nAccuracy as max. distance between points: "))
         (setq *SelectByEntity* (cons (car *SelectByEntity*) entity))))))
 [color=darkred](setq entity (car entity))[/color]
 (if (> (getvar "CmdActive") 0)
   (command (SelectByEntity entity (car *SelectByEntity*) (cdr *SelectByEntity*)))
   (sssetfirst
     nil
     (SelectByEntity entity (car *SelectByEntity*) (cdr *SelectByEntity*))))
 (princ))

I'm not sure but mine would send th selection set to the active command, else do the sssetfirst. Anyhow, that's how I've done it previously - allows for the princ to still be issued at the end of the command.

Edited by irneb
Fixed bug in code
Link to comment
Share on other sites

Glad to help, though re-reading your first post: You want to pick several polylines for use as the boundaries. AFAIK you can only send one boundary point list to ssget at a time, so you'll need to union / merge the selection sets:

 

http://forums.augi.com/showthread.php?138426-sel-sets-subfunctions

http://www.theswamp.org/index.php?topic=41526.5

 

Anyone know of a way to get around this? Say you've got 2 close PL's and want to use them as the WP points lists. All I can think of at the moment is command-calling "SELECT" and then "WP" followed by a loop to send each point in turn, rinse & repeat for each PL, then use ssget with "P" (for previous). But that's going to clutter the command-line no-end, not to mention it might be very slow indeed.

Link to comment
Share on other sites

Hi Irneb,

 

Yes, Well spotted! I did want to select multiple polylines but didn't want to hassle you guys for another amendment to the code. It would be great if someone can solve this but the code that has been posted is very usable, so no both if you can't.

Many thanks.

Rick

Link to comment
Share on other sites

Here's the "simple" way of doing it through the Select command:

(defun GetPointList  (entity accuracy / points delta index)
 (setq delta (/ (vlax-curve-GetDistAtParam entity (vlax-curve-GetEndParam entity))
                accuracy)
       index (- delta))
 (repeat (fix accuracy)
   (setq points
          (cons
            (trans (vlax-curve-GetPointAtDist entity (setq index (+ index delta)))
                   0
                   1)
            points)))
 points)
(defun c:SelectByEntities1  (/ eSS n)
 (if (setq eSS (ssget '((0 . "CIRCLE,ELLIPSE,SPLINE,LWPOLYLINE,POLYLINE"))))
   (progn (command "._SELECT")
          (repeat (setq n (sslength eSS))
            (command "_WP")
            (foreach pt  (GetPointList (ssname eSS (setq n (1- n))) 100.0)
              (command "_Non" pt))
            (command ""))
          (command "")
          (sssetfirst nil (ssget "_P"))))
 (princ))

Note this won't work as a transparent command - seeing as it's calling another command itself.

Link to comment
Share on other sites

And the more complex one using selection set union (as my ss-union2 from the augi thread)

(defun ss-union2 (ss1 ss2 / ss)
 (setq ss (ssadd))
 (foreach e (list-union (ss->list ss1) (ss->list ss2)) (ssadd e ss))
 ss)

(defun ss->list (ss / n lst)
 (setq n (sslength ss))
 (while (>= (setq n (1- n)) 0) (setq lst (cons (ssname ss n) lst)))
 lst)

(defun list-subtract (lst1 lst2 / )
 (vl-remove-if (function (lambda (item) (vl-position item lst2))) lst1))

(defun list-union (lst1 lst2 /  )
 (append lst1 (list-subtract lst2 lst1)))

(defun c:SelectByEntities2  (/ eSS n ss)
 (if (setq eSS (ssget '((0 . "CIRCLE,ELLIPSE,SPLINE,LWPOLYLINE,POLYLINE"))))
   (progn (setq ss (ssadd))
     (repeat (setq n (sslength eSS))
       (gc)
       (setq ss (ss-union2 ss (SelectByEntity (ssname eSS (setq n (1- n))) "_WP" 100.0))))
     (if (> (getvar "CmdActive") 0)
       (command ss)
       (sssetfirst nil ss))))
 (princ))

At least this one can be used transparently.

Link to comment
Share on other sites

Irneb,

 

Brilliant! It took me a minute to work out i needed to add it to the other code you posted but got there in the end. I used the "selection set union" so i can use it transparently. Again, thank you very much for your efforts.

 

Rick

Link to comment
Share on other sites

Glad to help. Just remember that it might become slowish if there are 10000's of entities to go through - selection set unions aren't too fast with huge quantities of entities.

 

Sorry about not including the SelectByEntity function (again). Though it's actually from Lee's post. I simply renamed the variables to be more readable.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...