Jump to content

Copy multiple text contents to nearest text (multiples)


Isaac26a

Recommended Posts

Hi everyone, I'd like to ask if you know a way to copy the contents of the text in yellow to the texts in gray in a simple way, or do you have any ideas to work around it, thanks for taking your time.

sample.jpg

 

sample.dwg

Edited by Isaac26a
Link to comment
Share on other sites

It appears that in image the 2 text overlap so it should be easy you get a selection set of one of the texts say yellow, then look for another text at that location, if found update the grey text. It would be a lisp. 

Link to comment
Share on other sites

In many of them you could say they overlap, but not in all of them, how can I search for a text in 'lets say a radius of 0.3'?, so far If I understand right 

1. I should make a selection set of the texts in yellow (different layer and color, so should not be a problem)

2. Make a selection set of the texts in gray (so far ok)

How can I search for each one of the texts in gray from every insertion point of the texts in yellow?, then copying and replacing text wouldn't be much of a problem, and make the loop.

Link to comment
Share on other sites

16 minutes ago, dan20047 said:

If you don't mind manually picking source & destination, try this:

Thanks dan20047, but I don't see how this can help me, I actually do it kind of manually, (created a lisp) to pick one by one, pick the source and pick the destination and the destination text is replaced by the source text, but it takes time.

Still working on the lisp to achieve it, if I have it soon I'll post it so you (all) can help me make it faster, thanks.

 

By the way a question, I started with this:

   (princ "\nSelect a text with the source data: \n")
   (while (not (setq stx1 (ssget ":S:E" '((0 . "*TEXT")))))
      (princ "\nSelect a text with the source data: \n")
   )
   (setq lyr1 (cdr (assoc 8 (entget (ssname stx1 0)))))
   (princ "\nSelect a text in the destination layer: \n")
   (while (not (setq stx2 (ssget ":S:E" '((0 . "*TEXT")))))
      (princ "\nSelect a text in the destination layer: \n")
   )
   (setq lyr2 (cdr (assoc 8 (entget (ssname stx2 0)))))
   (setq ss1 (ssget "_X" '((0 . "TEXT") (8 . "cvl_ras_tx")))  	;;; (cons 8 lyr1)

And wanted to make the ss1 picking the entity but 

(setq ss1 (ssget "_X" '((0 . "TEXT") (8 . lyr1))))

wouldn't work so had to do it (8 . "cvl_ras_tx"), and then it worked, why is that?, as you see I tried (cons 8 lyr1) but neither worked

Link to comment
Share on other sites

11 minutes ago, Isaac26a said:

 


(setq ss1 (ssget "_X" '((0 . "TEXT") (8 . lyr1))))

wouldn't work so had to do it (8 . "cvl_ras_tx"), and then it worked, why is that?, as you see I tried (cons 8 lyr1) but neither worked

It works with list instead of quote because you want to evaluate the data

(setq ss1 (ssget "_X" (list '(0 . "TEXT") (cons 8 lyr1))))

 

see http://www.lee-mac.com/quote.html for explanation

Link to comment
Share on other sites

25 minutes ago, dan20047 said:

It works with list instead of quote because you want to evaluate the data

Thanks for the explanation and the reference. dan20047

Link to comment
Share on other sites

1 hour ago, Isaac26a said:

Thanks dan20047, but I don't see how this can help me, I actually do it kind of manually, (created a lisp) to pick one by one, pick the source and pick the destination and the destination text is replaced by the source text, but it takes time.

Still working on the lisp to achieve it, if I have it soon I'll post it so you (all) can help me make it faster, thanks.

 

If you are manually picking source then destination, you could try this from Lee Mac. http://lee-mac.com/copytext.html

 

Link to comment
Share on other sites

Thanks Steven, finally finished my lisp and it's working, now does anyone have a better idea to improve it?

;;; By Isaac A.
;;; Select multiples texts and copy their content to nearest texts
;;; https://www.cadtutor.net/forum/topic/74035-copy-multiple-text-contents-to-nearest-text-multiples/

(defun c:cmt (/ cnt1 cnt2 dist ent1 ent2 ss1 ss2 stx1 stx2 tx1 tx2 lyr1 lyr2)
   (setvar "cmdecho" 0)
   (vl-cmdf "_.undo" "_begin")
   (setq *osmode (getvar "osmode"))
  
   (setvar "osmode" 0)
   (setq ss1 (ssget "_X" '((0 . "TEXT") (8 . "cvl_ras_tx")))
         ss2 (ssget "_X" '((0 . "TEXT") (8 . "urb_rasante")))
   )
   (setq cnt1 0)
   (while (< cnt1 (sslength ss1))
      (if (/= nil (assoc 11 (entget (ssname ss1 cnt1))))
         (setq pt1 (cdr (assoc 11 (entget (ssname ss1 cnt1))))
               cnt2 0
	       ent1 (entget (ssname ss1 cnt1))
               tx1 (assoc 1 ent1)
               dist 2
         )
         (setq pt1 (cdr (assoc 10 (entget (ssname ss1 cnt1))))
               cnt2 0
	       ent1 (entget (ssname ss1 cnt1))
               tx1 (assoc 1 ent1)
               dist 2
         )
      )
      (while (< cnt2 (sslength ss2))
         (if (/= nil (assoc 11 (entget (ssname ss2 cnt2))))
            (setq pt2 (cdr (assoc 11 (entget (ssname ss2 cnt2))))
            )
            (setq pt2 (cdr (assoc 10 (entget (ssname ss2 cnt2))))
            )
         )
	 (if (< (distance pt1 pt2) dist)
            (progn
               (setq dist (distance pt1 pt2)
                     ent2 (entget (ssname ss2 cnt2))
                     tx2 (assoc 1 ent2)
               )
	       (entmod (subst tx1 tx2 ent2))
            )
         )
         (setq cnt2 (1+ cnt2))
      )
     
      (setq cnt1 (1+ cnt1))
   )

   (setvar "osmode" *osmode)
   (vl-cmdf "_.undo" "_end")
   (princ) 
)

 

  • Like 1
Link to comment
Share on other sites

Another way is use the text pt and make a polygon can be just 4 sides a few more sides can work better, then get its co-ordinates, then erase (entlast) a simple (ssget "CP" co-ords (list (cons 0 "TEXT")(cons 8 layer))) this saves searching  through the other text selection set.


 

(command "ploygon" Pt "I" rad) 
(setq co-ord (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget (car plent)))))
(command "erase" (entlast) "")
(setq ss (ssget "CP" co-ords (list (cons 0 "TEXT")(cons 8 layer))))

 

  • Like 1
Link to comment
Share on other sites

51 minutes ago, BIGAL said:

Another way is use the text pt and make a polygon can be just 4 sides a few more sides can work better, then get its co-ordinates, then erase (entlast) a simple (ssget "CP" co-ords (list (cons 0 "TEXT")(cons 8 layer))) this saves searching  through the other text selection set.

 

Seems to be an interesting option, I wouldn't have imagined it, maybe I should try to test it on the benchmark lisp I saw the other day Ronjonp used, although I'm not sure how it works or if it works for a complete lisp, maybe the search through the selection set takes longer.

Thanks for your help Alan.

Link to comment
Share on other sites

23 hours ago, Isaac26a said:

does anyone have a better idea to improve it?

 

 

Here is what i came up with. Basically the same as yours except

using foreach function

looking at 72 to get the correct point.

Ignore distance. so if *dist = 25 but closest text is 35 it won't change

Removes changed text from selection set to speed up later searches.

removing text also speed up if their are more entity's in SS1 then SS2.

 

;;----------------------------------------------------------------------------;;
;; Select multiples texts and copy their content to nearest texts
(defun C:CMT (/ dist *dist PT1 PT2 ent ss1 ss2 obj)
  (setvar "cmdecho" 0)
  (vl-cmdf "_.undo" "_begin")
  (setq *osmode (getvar "osmode"))
  (setvar "osmode" 0)
  (setq SS1 (ssget "_X" '((0 . "TEXT") (8 . "cvl_ras_tx")))  ;copy
        SS2 (ssget "_X" '((0 . "TEXT") (8 . "urb_rasante"))) ;replace
  )
  (if SS1
    (foreach txt1 (mapcar 'cadr (ssnamex SS1))
      (if (= (cdr (assoc 72 (entget txt1))) 0)
        (setq PT1 (cdr (assoc 10 (entget txt1))))
        (setq PT1 (cdr (assoc 11 (entget txt1))))
      )
      (setq *dist 1000 ;change *dist value to ignore items farther away but still cloest item.
            ent nil    ;resets ent error checking if match is made.
      ) 
      (if (> (sslength SS2) 0)
        (progn
          (foreach txt2 (mapcar 'cadr (ssnamex SS2))
            (if (= (cdr (assoc 72 (entget txt2))) 0)
              (setq PT2 (cdr (assoc 10 (entget txt2))))
              (setq PT2 (cdr (assoc 11 (entget txt2))))
            )
            (setq dist (distance PT1 PT2))
            (if (< dist *dist)
              (progn
                (setq *dist dist)
                (setq ent txt2)
              )
            )
          )
          (if ent ;might not be any matches if beond ignore distance
            (progn
              (setq tx1 (assoc 1 (entget txt1)))
              (setq obj (entget ent))
              (entmod (subst tx1 (assoc 1 obj) obj))
              (ssdel ent SS2) ;removes changed text from selection set so later searches are faster
            )
          )
        )
      )
    )
  )
  (setvar "osmode" *osmode)
  (vl-cmdf "_.undo" "_end")
  (princ)
)

 

Edited by mhupp
  • Like 1
Link to comment
Share on other sites

You have many overlapping texts in many places so its better to overkill the duplicates.

(defun c:Test ( / int sel ent get ins txt src tar srt)
  ;; Tharwat - 21.Nov.2021	;;
  (and (setq int -1 sel (ssget "_:L" '((0 . "TEXT") (8 . "urb_rasante,CVL_RAS_TX"))))
       (while (setq int (1+ int) ent (ssname sel int))
         (setq get (entget ent)
               ins (cdr (assoc 10 get))
               txt (cdr (assoc 01 get))
               )
         (or (and (= (cdr (assoc 8 get)) "CVL_RAS_TX")
                  (setq src (cons (list ins txt get) src))
                  )
             (setq tar (cons (list ins txt get) tar))
             )
         )
       (while (and src tar
                   (setq itm (car tar))
                   (setq srt (vl-sort src (function (lambda (j k) (< (distance (car itm) (car j))
                                                                     (distance (car itm) (car k)))
                                                      )
                                                    )
                                      )
                         )
                   (entmod (subst (cons 1 (cadar srt)) (assoc 1 (last itm)) (last itm)))
                   (setq tar (cdr tar)
                         src (cdr srt))
                   )
         )
       )
  (princ)
  ) (vl-load-com)

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Well I tested the programs in a much larger scale (about 1550) text for each selection set and the results were

Tharwat's took  0:16.27

Mine  took          2:50:15

Mhupp's gives me an ; error: too many arguments wich I couldn't find where it is, as I see it, has a better improvement than mine

Bigal's didn't knew how to adapt it, maybe I should keep studying lisp wich I will, but at the moment don't know how

 

20 hours ago, Tharwat said:

You have many overlapping texts in many places so its better to overkill the duplicates.

Yes, you're right I didn't see that before, but when I downloaded the sample again saw it, Although I tried overkill, I haven't checked but in my old 2010 C3d version overkill doesn't have an option for duplicated texts so it didn't work using it, have to see in my 2019 version if it does.

 

Thank you guys (Dan20047, Steven P, BigAl, Mhupp and Tharwat) for caring and helping.

Edited by Isaac26a
Link to comment
Share on other sites

4 hours ago, Isaac26a said:

Mhupp's gives me an ; error: too many arguments wich I couldn't find where it is, as I see it, has a better improvement that mine

 

Fat fingered it!

 

(if (> (sslength SS2 0))
to
(if (> (sslength SS2) 0)

 

Link to comment
Share on other sites

Looking over your code @Tharwat very nice. I will use this when comparing entity's from now on. I also saw something awhile back for entmod. When pulling the assoc # don't use cdr on them. makes it about 5-10% faster.

 

(setq get (entget ent)
      ins (cdr (assoc 10 get))
      txt (assoc 01 get)
)
....
(entmod (subst (cadr srt) (cadr itm) (last itm)))
(entmod (subst stxt ctxt get)) ;if they are not in a list



(setq get (entget ent)
      ins (cdr (assoc 10 get))
      txt (cdr (assoc 01 get))
)
....
(entmod (subst (cons 1 (cadar srt)) (assoc 1 (last itm)) (last itm)))

 

Edited by mhupp
  • Thanks 1
Link to comment
Share on other sites

8 hours ago, mhupp said:

Fat fingered it!

Yes, Thanks for the correction, I tested your code with the correction, and It took 1:16.88 wich is almost half of the time that mine took, I'll study the mods both of you made, so I can apply it to other programs, and keep improving. Thanks again for your help.

Link to comment
Share on other sites

Here is another way .. checks that there is something within a distance of 1.5 ( based on the sample drawing ). Should be fairly fast 🍻

(defun c:foo (/ a b c d el r s)
  ;; RJP » 2021-11-22
  (cond	((setq s (ssget "_X" '((0 . "TEXT") (8 . "urb_rasante,CVL_RAS_TX"))))
	 (setq d 1.5)
	 (foreach e (mapcar 'cadr (ssnamex s))
	   (if (= "CVL_RAS_TX" (cdr (assoc 8 (setq el (entget e)))))
	     (setq a (cons (list (cdr (assoc 11 el)) (cdr (assoc 1 el))) a))
	     (setq b (cons (list (cdr (assoc 11 el)) e) b))
	   )
	 )
	 (setq a (vl-sort a '(lambda (r j) (< (caar r) (caar j)))))
	 (setq b (vl-sort b '(lambda (r j) (< (caar r) (caar j)))))
	 (while	(setq c (car a))
	   (setq a (cdr a))
	   (if (vl-some '(lambda (x) (<= (distance (car c) (car (setq r x))) d)) b)
	     (list (entmod (append (entget (cadr r)) (list (cons 1 (cadr c)))))
		   (setq b (vl-remove r b))
	     )
	     (entmake (list '(0 . "circle") (cons 10 (car c)) '(40 . 5) '(8 . "NoMatch")))
	   )
	 )
	)
  )
  (princ)
)

 

Edited by ronjonp
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

25 minutes ago, ronjonp said:

Here is another way .. checks that there is something within a distance of 1.5 ( based on the sample drawing ). Should be fairly fast 🍻

Thanks Ronjonp, another impresive code to study, in the same test sample the (1550 texts) it took 0:04.07 much more than fairly fast. Hats off to all of you guys, thanks.

Link to comment
Share on other sites

10 minutes ago, Isaac26a said:

Thanks Ronjonp, another impresive code to study, in the same test sample the (1550 texts) it took 0:04.07 much more than fairly fast. Hats off to all of you guys, thanks.

Glad to help 🍻

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...