supercell Posted November 26, 2012 Posted November 26, 2012 (edited) 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 November 26, 2012 by supercell Quote
Tharwat Posted November 26, 2012 Posted November 26, 2012 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) Quote
MSasu Posted November 26, 2012 Posted November 26, 2012 @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. Quote
Lee Mac Posted November 26, 2012 Posted November 26, 2012 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. 1 Quote
supercell Posted November 26, 2012 Author Posted November 26, 2012 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 Quote
supercell Posted November 26, 2012 Author Posted November 26, 2012 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. Quote
MSasu Posted November 27, 2012 Posted November 27, 2012 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. Quote
MSasu Posted November 27, 2012 Posted November 27, 2012 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] ) ) Quote
MSasu Posted November 27, 2012 Posted November 27, 2012 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] ) ) Quote
irneb Posted November 27, 2012 Posted November 27, 2012 (edited) (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 November 28, 2012 by irneb Fixed bug in code Quote
supercell Posted November 27, 2012 Author Posted November 27, 2012 Tharwat, Lee Mac, MSasu and Irneb, Thank you all for your code and time. It works a treat. Many thanks Rick Quote
irneb Posted November 28, 2012 Posted November 28, 2012 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. Quote
supercell Posted November 28, 2012 Author Posted November 28, 2012 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 Quote
irneb Posted November 29, 2012 Posted November 29, 2012 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. Quote
irneb Posted November 29, 2012 Posted November 29, 2012 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. Quote
supercell Posted November 29, 2012 Author Posted November 29, 2012 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 Quote
irneb Posted November 29, 2012 Posted November 29, 2012 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. Quote
Recommended Posts
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.