poffenberger Posted July 5, 2017 Share Posted July 5, 2017 I need help with a lisp to move multiple, (3)lines of text, to a point or an insertion point. I was helped the other day by a awesome individual who instructed me on using the Point Manager and then a lisp to move text to point, and it worked great. I'd like to somehow incorporate similar logic to move (3) lines of text (multiple (3)lines of text) to a common point relative to each set of (3)line text strings. Please see attachment for a visual narrative. Any help will be greatly appreciated. I'll also share the txt2pt code in the hopes that it maybe tweaked to work in this scenario. I'd like to thank you all advance, Paul Move Green Text.dwg Move Green Text.pdf txt2pt.LSP PtManagerV2-4.lsp Quote Link to comment Share on other sites More sharing options...
ronjonp Posted July 6, 2017 Share Posted July 6, 2017 (edited) I need help with a lisp to move multiple, (3)lines of text, to a point or an insertion point. I was helped the other day by a awesome individual who instructed me on using the Point Manager and then a lisp to move text to point, and it worked great. I'd like to somehow incorporate similar logic to move (3) lines of text (multiple (3)lines of text) to a common point relative to each set of (3)line text strings. Please see attachment for a visual narrative. Any help will be greatly appreciated. I'll also share the txt2pt code in the hopes that it maybe tweaked to work in this scenario. I'd like to thank you all advance, Paul Based on your example drawing .. try this: (defun c:foo (/ p t1 t2 t3 x y) ;; RJP - 07.07.2017 ;; Load visual lisp (vl-load-com) ;; This is a the y offset for text based on example drawing ;; (setq y 0.145833) (cond ;; If no text on layer "OLI_IDTEXT" are in the drawing exit and prompt ((null (setq t1 (ssget "_x" '((0 . "text") (8 . "OLI_IDTEXT"))))) (print "'OLI_IDTEXT' text not found!") ) ;; If no text on layer "OLI_ANTEXT" are in the drawing exit and prompt ((null (setq t2 (ssget "_x" '((0 . "text") (8 . "OLI_ANTEXT"))))) (print "'OLI_ANTEXT' text not found!") ) ;; Rock and roll .. compile a list of all the green text to be moved as a list of ((<alignment_point> . ename)...) ((setq t2 (mapcar '(lambda (x) (cons (cdr (assoc 11 (entget x))) x)) (mapcar 'cadr (ssnamex t2))) ) ;; Changed to be a 2X factor of the text height in drawing (setq y (* 2. (cdr (assoc 40 (entget (cdr (car t2))))))) ;; Foreach base text (foreach base (mapcar 'cadr (ssnamex t1)) ;; Grab the alignment point to move to (setq p (cdr (assoc 11 (entget base)))) (if ;; Sort the 'green text' list by distance (and (setq t3 (vl-sort t2 '(lambda (a b) (< (distance p (car a)) (distance p (car b)))))) ;; and check that we have at least 3 items in the sorted list (>= (length t3) 3) );; For the first 3 items in sorted green text list ( closest to base text ) (foreach x (list (car t3) (cadr t3) (caddr t3)) ;; Move the text using the base text x value and incrementing the y value by 2X the text height (vlax-invoke (vlax-ename->vla-object (cdr x)) 'move (car x) (setq p (list (car p) (+ y (cadr p)) 0.0)) ) ;; Remove the item from the 'green text' list so it won't get processed twice (setq t2 (vl-remove x t2)) ) ) ) ) ) ;; Shhhh (princ) ) Edited July 7, 2017 by ronjonp added comments and fixed typo Quote Link to comment Share on other sites More sharing options...
poffenberger Posted July 6, 2017 Author Share Posted July 6, 2017 ronjonp, Thanks for the reply. I pasted your code in the visual lisp editor and saved to a .lsp file. Loaded application without any errors. In my drawing at the command line I typed foo then nothing... no prompts, errors nothing. Please let me know if my process is wrong. From just researching the forums I believe the foo after the c: is the command name? Thanks Paul Quote Link to comment Share on other sites More sharing options...
ronjonp Posted July 6, 2017 Share Posted July 6, 2017 Did you run it on your "Move Green Text" test drawing? It worked for me. Quote Link to comment Share on other sites More sharing options...
poffenberger Posted July 7, 2017 Author Share Posted July 7, 2017 You are awesome!! I"m new to this coding thing so I'd like to ask you 2 things? On a scale of 1-10 (10 being the hardest) how difficult was this? Any recommendation on a starting point? Macro's - Lisp - Scripts. Do they sort of line up in a logical order to learn. Thanks again for everything. Paul Quote Link to comment Share on other sites More sharing options...
Roy_043 Posted July 7, 2017 Share Posted July 7, 2017 @ronjonp: There seems to be a typo here: (foreach x t3 (setq t2 (vl-remove t3 t2))) And you probably want to only remove the first 3 t3 items from t2. Quote Link to comment Share on other sites More sharing options...
poffenberger Posted July 7, 2017 Author Share Posted July 7, 2017 Roy_043, This routine seems to work great, is there something I'm missing? Quote Link to comment Share on other sites More sharing options...
ronjonp Posted July 7, 2017 Share Posted July 7, 2017 (edited) Roy_043, This routine seems to work great, is there something I'm missing? Roy is correct there was a typo ( actually a couple ) ( fixed above ) .. the reason it worked fine is because nothing was being removed from the 't2' list because I was calling the whole list 't3' rather than the individual elements of 't3'. Scale of difficulty for me, I'd give it a 2 . As far as learning goes, just keep trying to understand what routines are given to you .. I'll comment the code above so you can learn from it . Edited July 7, 2017 by ronjonp Quote Link to comment Share on other sites More sharing options...
poffenberger Posted July 7, 2017 Author Share Posted July 7, 2017 ronjonp, I made an error in the move green text dwg file. For some reason I scaled the dwg by a factor of 1.5, so your routine works but the distance between the 4 lines of text is too great. Please find attached dwg at the proper scale and could I bother to repeat your magic on the move red text drawing. Thanks again Move Red Text.dwg Quote Link to comment Share on other sites More sharing options...
ronjonp Posted July 7, 2017 Share Posted July 7, 2017 Change: (setq y 0.218751) to (setq y 0.145833) .. I also commented the code above so take a look. Actually .. I modified the code above so it will use the 2X the text height as the Y spacing so it should not matter now. I can't believe you used to do this manually! Quote Link to comment Share on other sites More sharing options...
poffenberger Posted July 7, 2017 Author Share Posted July 7, 2017 Yes it's very time consuming Sorta new to this "production" type drafting. I'm definitely going to start looking at other tasks that can be simplified. So if I'm understanding you correctly; I just need to make a new lsp file from the code above? (the one that you originally made, but is now modified) Thanks so much, hopefully I can pay it forward some day. Quote Link to comment Share on other sites More sharing options...
ronjonp Posted July 7, 2017 Share Posted July 7, 2017 Yes it's very time consuming Sorta new to this "production" type drafting. I'm definitely going to start looking at other tasks that can be simplified. So if I'm understanding you correctly; I just need to make a new lsp file from the code above? (the one that you originally made, but is now modified) Thanks so much, hopefully I can pay it forward some day. I did modify the original code for you. Hopefully you can learn from the comments. Quote Link to comment Share on other sites More sharing options...
poffenberger Posted July 7, 2017 Author Share Posted July 7, 2017 Thanks so much, I hope to pay it forward somday. Quote Link to comment Share on other sites More sharing options...
poffenberger Posted July 11, 2017 Author Share Posted July 11, 2017 ronjonp, Your code is working fine and is much appreciated. On the bigger drawings some of the text gets confused and lands up misplaced so to speak. Would there be a way to pause for user input and allow me to select the text I want, then have that selection move automatically; then repeat as necessary. Perhaps something similar to below? (getpoint [ptlst] [prompt]) Waits for a user-input point and returns the coordinates of the point as a list. If the optional point list argument is supplied, a drag line appears from the point argument to the crosshairs. The optional prompt must be a string and appears on the command line when the program pauses while the user is selecting the point(s). Thanks, Paul Quote Link to comment Share on other sites More sharing options...
ronjonp Posted July 11, 2017 Share Posted July 11, 2017 ronjonp, Your code is working fine and is much appreciated. On the bigger drawings some of the text gets confused and lands up misplaced so to speak. Would there be a way to pause for user input and allow me to select the text I want, then have that selection move automatically; then repeat as necessary. Perhaps something similar to below? (getpoint [ptlst] [prompt]) Waits for a user-input point and returns the coordinates of the point as a list. If the optional point list argument is supplied, a drag line appears from the point argument to the crosshairs. The optional prompt must be a string and appears on the command line when the program pauses while the user is selecting the point(s). Thanks, Paul Maybe post your drawing where results aren't as desired .. perhaps there are other rules to look for. Quote Link to comment Share on other sites More sharing options...
poffenberger Posted July 11, 2017 Author Share Posted July 11, 2017 ronjonp, Attached are (2)dwg's. The yellow text in the dwg named prior to foo command are the pieces of text getting confused. The dwg named foo command executed shows where the yellow text is ending up and pushing other red text down further in the drawing. Thanks, Paul PRIOR TO FOO COMMAND.dwg FOO COMMAND EXECUTED.dwg Quote Link to comment Share on other sites More sharing options...
ronjonp Posted July 11, 2017 Share Posted July 11, 2017 Question: Is the text that is going to be moved always a consistent color? Your example drawing has them all as red. If so, add the red part to the filter (null (setq t2 (ssget "_x" '((0 . "text") (8 . "OLI_ANTEXT")(62 . 1))))) Quote Link to comment Share on other sites More sharing options...
poffenberger Posted July 11, 2017 Author Share Posted July 11, 2017 At this point the answer would be no(they're all the same color). I've been changing the colors for clarity purposes. My first thought was to change the 'confused' text to another layer, which means I'd be hand selecting each one. This would be fine if it's the best solution. I was just wondering if there was perhaps something else we could do. I do appreciate all your help. Thanks again, Paul Quote Link to comment Share on other sites More sharing options...
ronjonp Posted July 11, 2017 Share Posted July 11, 2017 I think I might have an idea .. will post something later. Quote Link to comment Share on other sites More sharing options...
ronjonp Posted July 11, 2017 Share Posted July 11, 2017 Try this version. It only grabs text within a specified max distance (setq maxd (* y 8.)) .. From my testing this approach works well on your drawing. I also left a couple of double check items in the code to circle base texts not processed and a line to show where the text was and where it moved to. Give it a go! (defun c:foo (/ maxd p t1 t2 t3 x y) ;; RJP - 07.11.2017 ;; Load visual lisp (vl-load-com) ;; This is a the y offset for text based on example drawing ;; (setq y 0.145833) (cond ;; If no text on layer "OLI_IDTEXT" are in the drawing exit and prompt ((null (setq t1 (ssget "_X" '((0 . "text") (8 . "OLI_IDTEXT"))))) (print "'OLI_IDTEXT' text not found!") ) ;; If no text on layer "OLI_ANTEXT" are in the drawing exit and prompt ((null (setq t2 (ssget "_X" '((0 . "text") (8 . "OLI_ANTEXT"))))) (print "'OLI_ANTEXT' text not found!") ) ;; Rock and roll .. compile a list of all the green text to be moved as a list of ((<alignment_point> . ename)...) ((setq t2 (mapcar '(lambda (x) (cons (cdr (assoc 11 (entget x))) x)) (vl-remove-if 'listp (mapcar 'cadr (ssnamex t2))) ) ) ;; Changed to be a 2X factor of the text height in drawing (setq y (* 2. (cdr (assoc 40 (entget (cdr (car t2))))))) ;; Max distance allowed for closest results ( text height * 15 ) (setq maxd (* y 8.)) ;; Foreach base text (foreach base (mapcar 'cadr (ssnamex t1)) ;; Grab the alignment point to move to (setq p (cdr (assoc 11 (entget base)))) (if ;; Sort the 'green text' list by distance (and (setq t3 (vl-sort t2 '(lambda (a b) (< (distance p (car a)) (distance p (car b)))))) ;; and check that we have at least 3 items in the sorted list (>= (length t3) 3) );; If the closest items are with the max distance set (if (<= (distance p (car (caddr t3))) maxd) ;; For the first 3 items in sorted green text list ( closest to base text ) (foreach x (list (car t3) (cadr t3) (caddr t3)) ;; Move the text using the base text x value and incrementing the y value by 2X the text height (vlax-invoke (vlax-ename->vla-object (cdr x)) 'move (car x) (setq p (list (car p) (+ y (cadr p)) 0.0)) ) ;; Line to check where text is moving (entmakex (list '(0 . "line") '(8 . "_RJPCheck") (cons 10 (car x)) (cons 11 p) '(62 . 30)) ) ;; Remove the item from the 'green text' list so it won't get processed twice (setq t2 (vl-remove x t2)) ) ;; Draw a circle to show that some 'base' text were not processed (entmakex (list '(0 . "circle") '(8 . "_RJPCheck") (cons 10 p) (cons 40 (* 0.5 maxd)) '(62 . 30)) ) ) ) ) ) ) ;; Shhhh (princ) ) Quote Link to comment Share on other sites More sharing options...
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.