MSasu Posted April 11, 2011 Posted April 11, 2011 I’m trying to design a routine that will clean a drawing of all 0 length lines; the first attempt was to create a selection set of all lines and parse it to compare the start point with end one (DXF codes 10 and 11). Unfortunately this is a very long process. It is possible to write a filter for SSGET function to select only the lines that have identical DXF codes 10 and 11? Thank you. Regards, Mircea Quote
Lee Mac Posted April 11, 2011 Posted April 11, 2011 I'm not sure that it is possible, since, if using the "-4" relational filter codes, the 10 and 11 DXF Group codes need to have values for comparison: (ssget "_X" '((0 . "LINE") (-4 . "=,=,=") (10 . [color=red]<Need something here>[/color]) (11 . [color=red]<Need something here>[/color]))) And since the Line entity does not have a DXF code representing Length, there is no unique value to filter for... This is the route I would most likely follow: (defun c:test ( / ss i e l ) (if (setq ss (ssget "_X" '((0 . "LINE")))) (repeat (setq i (sslength ss)) (setq e (ssname ss (setq i (1- i))) l (entget e) ) (if (equal (cdr (assoc 10 l)) (cdr (assoc 11 l)) 1e- (entdel e)) ) ) (princ) ) Quote
Tharwat Posted April 11, 2011 Posted April 11, 2011 No one can be faster than Lee . So here is my poor way . (defun c:TesT (/ sel ss i sset 1st 2nd obj) (setq sel (ssadd)) (setq ss (ssget "_x" '((0 . "LINE")))) (repeat (setq i (sslength ss)) (while (setq sset (ssname ss (setq i (1- i)))) (setq 1st (cdr (assoc 10 (setq ents (entget sset))))) (setq 2nd (cdr (assoc 11 ents))) (if (and (eq (car 1st) (car 2nd)) (eq (cadr 1st) (cadr 2nd)) ) (setq obj (ssadd sset sel)) ) ) ) (sssetfirst nil obj) (print (strcat (itoa (sslength obj)) " " " Line(s) found")) (princ) ) TharwaT Quote
Lee Mac Posted April 11, 2011 Posted April 11, 2011 (repeat (setq i (sslength ss)) (while (setq sset (ssname ss (setq i (1- i)))) Note that your code has a nested loop and so, after iterating through the inner while loop a number of times equal to the size of the selection set, it will then iterate through the repeat loop the same number of times. Quote
pBe Posted April 11, 2011 Posted April 11, 2011 (edited) (defun c:test (/ sset)(vl-load-com) (if (setq sset (ssget "X" '((0 . "LINE")))) (progn(foreach ob (vl-remove-if 'listp (mapcar 'cadr (ssnamex sset))) (if (/= (vla-get-length (vlax-ename->vla-object ob)) 0.0) (setq sset (ssdel ob sset)) ) ) (sssetfirst nil sset) ) ) ) Edited April 11, 2011 by pBe Oops Quote
alanjt Posted April 11, 2011 Posted April 11, 2011 (foreach ob (vl-remove-if 'listp (mapcar 'cadr (ssnamex sset))) Horribly, horribly, horribly inefficient. Quote
pBe Posted April 11, 2011 Posted April 11, 2011 Horribly, horribly, horribly inefficient. (ssget "_:L" '((0 . "LINE"))) (vlax-for objs (setq ss (vla-get-activeselectionset adoc)).... better? Quote
alanjt Posted April 11, 2011 Posted April 11, 2011 (ssget "_:L" '((0 . "LINE"))) (vlax-for objs (setq ss (vla-get-activeselectionset adoc)).... better? Much; or step through it with repeat/while and use (vlax-curve-getDistAtParam <Entity> (vlax-curve-getEndParam <Entity>)) You could also vlax-curve-getDistAtPoint and vlax-curve-getEndPoint. Either is fine. Quote
Tharwat Posted April 11, 2011 Posted April 11, 2011 Note that your code has a nested loop and so, after iterating through the inner while loop a number of times equal to the size of the selection set, it will then iterate through the repeat loop the same number of times. Thank you. So the While function is the wrong thing with repeat . I like lambda . (defun c:TesT (/ sel ss) (setq sel (ssadd)) (if (setq ss (ssget "_x" '((0 . "LINE")))) ((lambda (i / sset 1st 2nd obj) (while (setq sset (ssname ss (setq i (1+ i)))) (setq 1st (cdr (assoc 10 (setq ents (entget sset))))) (setq 2nd (cdr (assoc 11 ents))) (if (and (eq (car 1st) (car 2nd)) (eq (cadr 1st) (cadr 2nd)) ) (setq obj (ssadd sset sel)) ) ) (sssetfirst nil obj) ) -1 ) ) (princ) ) Quote
pBe Posted April 11, 2011 Posted April 11, 2011 Thanks Alan. Always wondered where i got hold of ssnamex and its advantage over (ssname objs 0) or (ssname objs counter), i could have sworn there's a reason why i did it that way before Hmmmmn a long time ago i guess Thanks for the heads up Alan Quote
alanjt Posted April 11, 2011 Posted April 11, 2011 Thank you. So the While function is the wrong thing with repeat . It's just not needed. Either use repeat OR while to step through the selection set; NOT BOTH. Quote
alanjt Posted April 11, 2011 Posted April 11, 2011 Thanks Alan. Always wondered where i got hold of ssnamex and its advantage over (ssname objs 0) or (ssname objs counter), i could have sworn there's a reason why i did it that way before Hmmmmn a long time ago i guess Thanks for the heads up Alan We've all used that method before. I didn't realize it was as slow as it is until we did a benchmark test of stepping through selection sets over at theSwamp. Quote
pBe Posted April 11, 2011 Posted April 11, 2011 I see, whre can i get the benchmark thingy? Swamp of course!! Ty Quote
Lee Mac Posted April 11, 2011 Posted April 11, 2011 In all of this I'd look to use the equal function to implement some tolerance on the comparison to account for the rounding of Doubles. Quote
Tharwat Posted April 11, 2011 Posted April 11, 2011 It's just not needed. Either use repeat OR while to step through the selection set; NOT BOTH. Thank you . I like lamb. I do like it too . Appreciated a lot. Quote
MSasu Posted April 15, 2011 Author Posted April 15, 2011 I wasn’t able to access the Forum for some time – thank you all for your replies. Thank you also for proposed solutions. Unfortunately those are close in performance to my own code. Seems that the ssget with filter provide a much faster access through database than by applying the same condition(s) trough ssname parse; maybe I wasn’t clear enough in my first post. For this reason I was looking for an appropriate ssget filter approach – which seems to don’t be possible to write, as Lee Mac has confirmed. Thank you again! Regards, Mircea Quote
Ahankhah Posted April 15, 2011 Posted April 15, 2011 I’m trying to design a routine that will clean a drawing of all 0 length lines... Assuming at least one zero length line exists in the drawing: Command: -PURGE Enter type of unused objects to purge [blocks/Dimstyles/Groups/LAyers/LTypes/MAterials/MUltileaderstyles/Plotstyles/SH apes/textSTyles/Mlinestyles/Tablestyles/Visualstyles/Regapps/Zero-length geometry/Empty text objects/All]: z Regenerating model. 1 zero-length geometric object deleted. (command"_.PURGE" "_Z") No one can be faster than Lee . I think this works even faster than Lee's code. Quote
MSasu Posted April 15, 2011 Author Posted April 15, 2011 Ahankhah, thank you for your solution – unfortunately this isn’t available on AutoCAD 2008. And, by the way, Tharwat was referring to Lee’s coding speed wich is legendary here. Regards, Mircea 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.