Get Coordinates of Text Entity

Get Coordinates of Text Entity

Anonymous
Not applicable
5,089 Views
14 Replies
Message 1 of 15

Get Coordinates of Text Entity

Anonymous
Not applicable

I am trying to write  a lisp to centralise a text item between two picked points

Finding the midpoint beween two picked points is easy, but how the devil can I find the coordinates of an text entity?

 

What I have so far is:

 

(defun c:test1 ( / ang dist newcoord oldcoord pt1 pt2 txt)
(setq txt (nentsel "\nselect text item to move"))
(setq oldcoord (entget (assoc 10 txt))); Get old coordinates

(setvar "osmode" 55)
(setq pt1 (getpoint "\npick first point: "))
(setq pt2 (getpoint "\npick second point: "))
(setq dist (distance pt1 pt2))
(setq ang (angle pt1 pt2))
(setq newcoord (polar pt1 ang (/ dist 2))); Get new coordinates
(command "_.move" txt oldcoord newcoord)  
 (setvar "osmode" 16439)
)

 

 

The

(assoc 10 txt)

 

bit is obviously wrong, I was trying to get the coordinates of txt

 

Please don't rewrite the code completly, I'm trying to learn

 

I'd prefer no V functions either, I'm not that advanced (yet)

 

Thank you in advance,

 

Simon

 

 

 

0 Likes
Accepted solutions (2)
5,090 Views
14 Replies
Replies (14)
Message 2 of 15

ВeekeeCZ
Consultant
Consultant
Accepted solution

Hi, its not that easy. First of all.. (entsel) returns list of (entname picked-point). To get entname you need to use (car (entsel)). Then you need to get a list of ents definition... (setq ed (entget entname)). THEN you can use (assoc 10 ed). But since a TEXT could have an alignment, you need to test point with code 11 first, when is this different of '(0 0 0), than text is not aligned and you can use 10 point. Otherwise, take (assoc 11 ed). See your the code.

Second. If you're messing with OSNAPS, you should return the initial value back in the end.... See my code, i used a temporary override osnaps modes.

 

(defun c:test1 ( / ang dist newcoord oldcoord pt1 pt2 txt)

  (setq ensel (entsel "\nselect text item to move")
	txt (car ensel)
	ed (entget txt))
  (if (equal '(0 0 0) (cdr (assoc 11 ed)))
    (setq oldcoord (cdr (assoc 10 ed)))
    (setq oldcoord (cdr (assoc 11 ed))))
  (setvar "osmode" 55)
  (setq pt1 (getpoint "\npick first point: "))
  (setq pt2 (getpoint "\npick second point: "))
  (setq dist (distance pt1 pt2))
  (setq ang (angle pt1 pt2))
  (setq newcoord (polar pt1 ang (/ dist 2))); Get new coordinates
  (command "_.move" txt "" "_none" oldcoord "_none" newcoord)
  (setvar "osmode" 16439)
)


(defun c:test2 ( / ss pt)
  (if (and (princ "\Text item to move, ")
	   (setq ss (ssget "_+.:E:S" '((0 . "TEXT"))))
	   (setq pt (if (equal '(0 0 0)
			       (cdr (assoc 11 (entget (ssname ss 0)))))
		      (cdr (assoc 10 (entget (ssname ss 0))))
		      (cdr (assoc 11 (entget (ssname ss 0))))))
	   )
    (command "_.MOVE" ss "" "_none" pt "_m2p" "_end,_mid,_int" PAUSE "_end,_mid,_int" PAUSE)
    (princ "¨Wrong selection of a SINGLE TEXT."))
  (princ)
)

 

;wrong
(setq oldcoord (entget (assoc 10 txt)))
;correct
(setq oldcoord (cdr (assoc 10 (entget (car txt)))))
0 Likes
Message 3 of 15

Anonymous
Not applicable

BeekeeCZ, please can I ask a couple of questions?

1) Why does it need two functions [test1 & test2]?

2) Are the following variables meant to be global, or doesn't it matter much?

 

; === Top statistic:
; Global variables: (ED ENSEL ENTSEL)
; Function definition (with number of arguments): ((C:TEST1 . 0))

; === Top statistic:
; Global variables: (PAUSE)
; Function definition (with number of arguments): ((C:TEST2 . 0))

0 Likes
Message 4 of 15

ВeekeeCZ
Consultant
Consultant

@Anonymous wrote:

BeekeeCZ, please can I ask a couple of questions?

1) Why does it need two functions [test1 & test2]?

>> you don't. TEST2 is just my version of the same. If you not gonna improve your TEST1 with returning OSNAP value and error handeling, than use mine.

 

2) Are the following variables meant to be global, or doesn't it matter much?

 

; === Top statistic:
; Global variables: (ED ENSEL ENTSEL)
; Function definition (with number of arguments): ((C:TEST1 . 0))

; === Top statistic:
; Global variables: (PAUSE)
; Function definition (with number of arguments): ((C:TEST2 . 0))


>> Sorry about that. ed and ensel I forgot to localize. Entsel is function, not variable.

PAUSE is a predifined variable similary to PI (3.14) with special function - it stops command execution for 1 user input, whatever it is (could be point, real number, string, it does not matter). Help here.

 

 

0 Likes
Message 5 of 15

Anonymous
Not applicable

Thank you very much BeekeeCZ

 

I shall be dissecting:

(setq oldcoord (cdr (assoc 10 (entget (car txt)))))

 to see how it works

0 Likes
Message 6 of 15

ВeekeeCZ
Consultant
Consultant

@Anonymous wrote:

Thank you very much BeekeeCZ

 

I shall be dissecting:

(setq oldcoord (cdr (assoc 10 (entget (car txt)))))

 to see how it works


 

Use this approach. 

Put a break point on the red...

 

(defun c:test ()
  (setq txt (entsel))
  (setq oldcoord (cdr (assoc 10 (entget (car txt)))))
)

...and watch a *last-value*

0 Likes
Message 7 of 15

Kent1Cooper
Consultant
Consultant
Accepted solution

Here's the way I would go about it.  I have a "pet peeve" about (ssget) always using the "Select objects: " prompt, always in the plural, so when I want to select a single object, I prefer to spell out my own prompt, which (entsel) lets me do.  And I prefer to do the same with (getpoint), rather than use pauses after Osnap mode calls, because the pauses leave the User with a prompt that's just "of ".

 

Also, if you check whether the 11-code value in entity data is (0 0 0) to decide whether the Text is left-justified or not, there's the risk [however slight] that you'll pick a piece of Text that's not left-justified but that happens to have its origin at (0 0 0), in which case it will use the wrong base point for the Move displacement.  This also will work in versions of AutoCAD old enough to not have the m2p Osnap mode.

 

(defun C:TM2P (/ txt tdata p1 p2); = Text to Midway between 2 Points
  (if
    (and
      (setq txt (car (entsel "\nSelect Text to move to Midway between 2 Points: ")))
      (= (cdr (assoc 0 (setq tdata (entget txt)))) "TEXT")
      (setq p1 (getpoint "\nFirst of 2 Points: "))
      (setq p2 (getpoint "\nSecond of 2 Points: "))
    ); and
    (command "_.move" txt ""
      "_none" (cdr (assoc (if (= (cdr (assoc 72 tdata)) (cdr (assoc 73 tdata)) 0) 10 11) tdata))
      "_none" (mapcar '/ (mapcar '+ p1 p2) '(2 2 2))
    ); command
    (prompt "\nNo Text selected, or 2 Points not picked.")
  ); if
  (princ)
); defun

That longest line is testing whether the Text is left-justified by looking at whether both 72- and 73-code entity data values are 0, in which case it takes the 10-code value for its insertion point, or not [any other justification], in which case it takes the 11-code value.  The following line is the equivalent of m2p Osnap.

Kent Cooper, AIA
0 Likes
Message 8 of 15

Anonymous
Not applicable

Thank you both. They're both excellent liitle lisps

 

Both do the job well too.

 

S

0 Likes
Message 9 of 15

ВeekeeCZ
Consultant
Consultant

@Kent1Cooper wrote:

Here's the way I would go about it.  I have a "pet peeve" about (ssget) always using the "Select objects: " prompt, always in the plural, so when I want to select a single object, I prefer to spell out my own prompt, which (entsel) lets me do....


It depends on the workflow. I prefer noun/verb type of selection so much that when I get a lisp with entsel selection, rewriting to ssget is always first thing I do (if it's possible because of the pick-point). In this case I actually never see the prompt... But I'am trying to use some pre sentence like "Need single block, " for other... usually.

0 Likes
Message 10 of 15

Kent1Cooper
Consultant
Consultant

@ВeekeeCZ wrote:
....

It depends on the workflow. I prefer noun/verb type of selection so much that when I get a lisp with entsel selection, rewriting to ssget is always first thing I do (if it's possible because of the pick-point). In this case I actually never see the prompt... ....


The one potential difficulty with that, as done in the test2 command, is that if there happens to be a pre-selection containing more than one Text object, it Moves all of them, using as the Move displacement base point the insertion point of one of them, but whichever happens to be first in the set, so you have no control over which one.  I worked up something I thought would account for that [adapted from another routine], but it's not working quite right yet -- maybe later.

Kent Cooper, AIA
0 Likes
Message 11 of 15

Anonymous
Not applicable

There's a fairly similar lisp that centres text or mxtext within a polyline rectangle called txtrec.lsp from Lee Mac located at:

 

http://www.cadtutor.net/forum/archive/index.php/t-90741.html?s=7fa1d902b8ab9d43bb25bf02dac1b745

 

But even he had to borrow other peoples code by the look of it !

 

I did try to adapt the code to use here, waaaaaaaay too complex for me

0 Likes
Message 12 of 15

ВeekeeCZ
Consultant
Consultant

@Kent1Cooper wrote:

The one potential difficulty with that, as done in the test2 command, is that if there happens to be a pre-selection containing more than one Text object, it Moves all of them, using as the Move displacement base point the insertion point of one of them, but whichever happens to be first in the set, so you have no control over which one.  I worked up something I thought would account for that [adapted from another routine], but it's not working quite right yet -- maybe later.


Wow, I never realized that. It's good to know, thx. If you'll figure it out, I'm certainly interested. Anyway, because this potential is low, I would suggest easy fix - add another condition for end (= 1 (sslength ss)).

0 Likes
Message 13 of 15

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

... if there happens to be a pre-selection containing more than one Text object, it Moves all of them....  I worked up something I thought would account for that [adapted from another routine], but it's not working quite right yet -- maybe later.


I got it working -- see attached TextToMidOf2.lsp with its TM2P command.

Kent Cooper, AIA
0 Likes
Message 14 of 15

ВeekeeCZ
Consultant
Consultant

@Kent1Cooper wrote:

@Kent1Cooper wrote:

... if there happens to be a pre-selection containing more than one Text object, it Moves all of them....  I worked up something I thought would account for that [adapted from another routine], but it's not working quite right yet -- maybe later.


I got it working -- see attached TextToMidOf2.lsp with its TM2P command.


 

Thank you for the solution. I must admit it's quite complex... I hoped in something simply clever 🙂 But I think the (= (sslength ss) 1) test would be for simple routines just enough.

 

I tried to find a version with less "redundancy". Not saying that is simpler. Just little tested...

0 Likes
Message 15 of 15

ВeekeeCZ
Consultant
Consultant

Hmm... maybe folding all into and function looks little bit weird if there is (or () T) and (tsel) cannot leave with nil value...

So maybe simply like this..

 

Spoiler
  (and (setq tss (ssget "_I" '((0 . "TEXT"))))
       (= (sslength tss) 1)
       (setq txt (ssname tss 0) tdata (entget txt)))
  (sssetfirst nil)
  (or txt
      (tsel))
  (redraw txt 3)
  (if (and (setq p1 (getpoint "\nFirst of 2 Points to move Text between: "))
	   (setq p2 (getpoint "\nSecond Point: "))
      ); and
    (command "_.move" txt "" ; then
      "_none" (cdr (assoc (if (= (cdr (assoc 72 tdata)) (cdr (assoc 73 tdata)) 0) 10 11) tdata))
      "_none" (mapcar '/ (mapcar '+ p1 p2) '(2 2 2))
    ); command
    (prompt "\nDid not pick 2 Points."); else
  ); if

 

 

0 Likes