SteveK Posted September 2, 2009 Posted September 2, 2009 Hi, I'm wanting to write a program that will return a list of all entities at a certain level. What I have is levels of text (possibly 4 levels high), each in columns though they vary in distance apart. See the attached jpeg to get the idea. Within each column the text is centered and has the same alignment X co-ordinate (ie in DXF Group Code 11) with the Y co-ordinate's equal spacing apart. The columns of text have no common distance between each other in the X or Y directions. So what I'm hoping I can get help with is code that will return a list of all the entities on a particular level (ie what is color coded in the jpeg) dependent on a level variable set at the start. For instance if I set this variable to 1 it will return the entities (preferably sorted by X Co-ordinate) that are yellow in the jpeg. Variable set to 3 would return the green entities. (NB. the text I'm dealing with is not color coded like the jpeg) I'd even welcome pseudo code if nothing else. My thinking at the moment is: - Create lists of entities with common X Co-ord. (though if there are hundreds of these texts it I'm not sure how I'd store them) - Then sort these lists by Y co-ordinate and returning the entity based on the level variable. If the level variable is set to 4 and an entity doesn't exist then it will skip that column/list. Thanks for any help PS. I don't think it's very helpful (I'm rather hoping for completely new code) but here's what I've written. This code doesn't take into account a level variable and it only returns a list of the highest text entities. It's gotten too messy to add anything else to it. [color=DimGray][color=Black](defun txtlst (ss / ssLst topEnt highestPoleTextLst)[/color] [color=Black] (setq ssLst (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))) (foreach e1 ssLst (setq lst (cons e1 lst)) (foreach e2 ssLst (If (= (cadr (assoc 11 (entget e1))) (cadr (assoc 11 (entget e2)))) (setq lst (cons e2 lst)))) (foreach en lst (If topEnt (If (< (caddr (assoc 11 (entget topEnt))) (caddr (assoc 11 (entget en)))) (setq topEnt en)) (setq topEnt en))) (If highestPoleTextLst (foreach en highestPoleTextLst (If (eq topEnt en) (If (< (caddr (assoc 11 (entget topEnt))) (caddr (assoc 11 (entget en)))) (subst en topEnt highestPoleTextLst) (setq topEnt nil))))) (If topEnt (setq highestPoleTextLst (cons topEnt highestPoleTextLst))) (setq lst nil) ) highestPoleTextLst[/color] [color=Black])[/color][/color] Quote
Lee Mac Posted September 2, 2009 Posted September 2, 2009 Steve - quick tip: look into the vl-sort function Quote
Lee Mac Posted September 2, 2009 Posted September 2, 2009 A similar example of the task you want to accomplish is in this thread, sorting Circles into rows: http://www.cadtutor.net/forum/showthread.php?t=36284 Quote
Patrick_35 Posted September 2, 2009 Posted September 2, 2009 Hi An example (defun trier_xy(/ add ele lst tab txt x) (defun add() (setq ele (vl-sort ele '(lambda(a b)(< (cadr (vlax-get a 'insertionpoint))(cadr (vlax-get b 'insertionpoint)))))) (if tab (setq tab (cons ele tab)) (setq tab (list ele)) ) ) (if (ssget (list (cons 0 "TEXT,MTEXT"))) (progn (vlax-for txt (setq sel (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object)))) (setq lst (cons txt lst)) ) (vla-delete sel) (foreach txt (vl-sort lst '(lambda(a b)(< (car (vlax-get a 'insertionpoint))(car (vlax-get b 'insertionpoint))))) (if (eq (car (vlax-get txt 'insertionpoint)) x) (setq ele (cons txt ele)) (progn (add) (setq x (car (vlax-get txt 'insertionpoint)) ele (list txt) ) ) ) ) (add) ) ) (reverse tab) ) (defun c:test(/ xy zz) (foreach zz (trier_xy) (foreach xy zz (terpri) (princ (vlax-get xy 'insertionpoint)) (princ xy) (princ (vla-get-textstring xy)) ) ) (princ) ) @+ Quote
SteveK Posted September 2, 2009 Author Posted September 2, 2009 Hey, thanks, you guys always pull through for me. I'll try use your example Patrick. EDIT: It worked great! Thanks again. Lee, thanks for the tips; regarding vl-sort, I don't think it's possible but just to be certain, you can't have one vl-sort function to sort by both X & Y? And I'm aware of sorting by one then the other using two vl-sort functions (which I should have used); when using a second vl-sort function is there a chance the order made from the first vl-sort function will be negated? Quote
Lee Mac Posted September 3, 2009 Posted September 3, 2009 I would have just used one vl-sort and used a Selection Set to collect all text that had the same x-coord as some text for comparison - as an example: (if (setq ss (ssget "_X" '((0 . "TEXT,MTEXT")))) (while (not (zerop (sslength ss))) (setq tEnt (ssname ss 0)) (if (setq nss (ssget "_X" (list '(0 . "TEXT,MTEXT") '(-4 . "=,*,*") (assoc 11 (entget tEnt))))) (progn (setq sorted (vl-sort (mapcar 'cadr (ssnamex nss)) (function (lambda (a b) (< (caddr (entget a)) (caddr (entget b))))))) (mapcar (function (lambda (x) (ssdel x ss))) sorted) ) ) ) ) Quote
SteveK Posted September 3, 2009 Author Posted September 3, 2009 I didn't know the ssget filter could be used like that. That's pretty helpful, thanks. A question, what if I wanted to manually select the selection set (ie remove "_X") and only select it once? And also, the line: (< (caddr (entget a)) (caddr (entget b))))))) Just if others use your code you meant: (< (caddr (assoc 11 (entget a))) (caddr (assoc 11 (entget b)))))))) Quote
Lee Mac Posted September 4, 2009 Posted September 4, 2009 A question, what if I wanted to manually select the selection set (ie remove "_X") and only select it once? This would be slightly harder, as the second selection set retrieves all the text in the database that meet the requirements, so it would be difficult to filter this without the user selecting the text again. An alternative would be to get the list of entities using the "_X" method, and then prompt for a selection by the user, and remove the entities in the list that are not present in the user selection set. :wink: Just if others use your code you meant: (< (caddr (assoc 11 (entget a))) (caddr (assoc 11 (entget b)))))))) Yes, sorry - I wrote it quickly ... too quickly it seems.. 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.