getting a text entity at a point

getting a text entity at a point

kpennell
Collaborator Collaborator
3,114 Views
25 Replies
Message 1 of 26

getting a text entity at a point

kpennell
Collaborator
Collaborator

Is there any way using 'ssget' that I can get a text entity at a non-specific point?  Like:

 

(ssget "X" '((0 . "TEXT")(11 318.03737793 9.13950144 0.0)))

 

Or will I have to retrieve all texts in the drawing, and do a compare?  Like this:

 

(and (= (cdr (assoc 0 ent1)) "TEXT") (equal (cdr (assoc 11 ent1)) '(318.03737793 9.13950144 0.0) 1e-8))

 

 

0 Likes
3,115 Views
25 Replies
Replies (25)
Message 2 of 26

Kent1Cooper
Consultant
Consultant

With coordinates like that, I suspect the latter will be needed, because AutoCAD really "knows" where it is to far more decimal places than that, and those extras [unless they happen to all be zeros] will mean it's not exactly where those rounded-off values indicate.

 

If you draw with Snap turned on, and if it were at, for instance [with Snap at 1/8" in Imperial units]:

 

(11 318.0 9.125 0.0)

 

then it would probably be able to find that, because there would be nothing in further-out decimal places to make the true coordinate values different from those shown.

Kent Cooper, AIA
0 Likes
Message 3 of 26

john.uhden
Mentor
Mentor
I think you can specify a point. Just place it outside the filter and skip the DXF code, as in (ssget "X" pt '((0 . "TEXT")))

John F. Uhden

0 Likes
Message 4 of 26

john.uhden
Mentor
Mentor
Considering what Kent advised, you may have to use (ssget "_C" p1 p2 '((0 . "TEXT"))) where p1 is slightly below and to the left of the PIQ and p2 is slightly up and to the right.

John F. Uhden

0 Likes
Message 5 of 26

kpennell
Collaborator
Collaborator

I tried the point outside the filter, but I got a "too many argument" error message.

 

I went with the ssget "C" approach and is working fine.  Too bad though, would have been neat.

0 Likes
Message 6 of 26

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:
.... you may have to use (ssget "_C" p1 p2 '((0 . "TEXT"))) where p1 is slightly below and to the left of the PIQ and p2 is slightly up and to the right.

There's a risk in that approach, depending on whether any drawn element of the Text content actually gets close enough to the point you're searching around:

 

TextSSGET.PNG

 

That's a selected-gripped-highlighted piece of Middle-justified Text, with the insertion-point grip showing in the middle.  A crossing window built around that point for (ssget) to search with would not find that Text if the window's corners are too close to the point itself, since it relies on drawn elements crossing the window, and won't "see" the insertion point if that's all that falls inside the window.  The same would be true if that were Left-justified and looking around the grip at the bottom left, and would also be possible with other combinations of justification and content.

 

So if you do it that way, you should probably use a window about the size of the Text height if you know what that will be, but even then there could be times when it would miss, such as possibly the above if there happened to be more than one space there [affected by the font, etc.].

Kent Cooper, AIA
0 Likes
Message 7 of 26

dbroad
Mentor
Mentor

This is a sample of the approach using point filters instead of "c"

 

(setq ss (ssget	"x"
		'((0 . "text")
		  (-4 . "<AND")
		  (-4 . ">,>,*")
		  (10 1.0 1.0 0.0)
		  (-4 . "<,<,*")
		  (10 3.0 3.0 0.0)
		  (-4 . "AND>")
		 )
	 )
)

This would get any text whose insertion point had  1<x<3 and 1<y<3 where z is not tested.  I am not sure whether this would find objects in multiple layouts or not but would be independent of zoom.  This would be for left justified text.  For any other text justification, the 11 code would need to be used.

Architect, Registered NC, VA, SC, & GA.
Message 8 of 26

john.uhden
Mentor
Mentor
I should have defined what "slightly" meant.. I guess it wouldn't be too bad to use a large crossing box since we typically tend not to overlap text.

This is a situation where I would bloat my own code to report any failures...
(or
(setq ss (ssget etc.))
(prompt "\nFailed to select any whatevers")
)

John F. Uhden

0 Likes
Message 9 of 26

1LandSurveyor
Enthusiast
Enthusiast

Hi @dbroad ,

 

I love your idea which basically solved my issue.

 

Although, in order to make my custom command more robust, i wondered if it could be possible to account for a OCS different than WCS, given that the supplied Insertion point is in WCS while DXF code 10 represents Entity's OCS.

 

Of course it could be processed after the (ssget "X" ...) statement, in a loop, but I would like to avoid that and would prefer the tweek to be inside the ssget statement direcly. 

 

Thanks,

0 Likes
Message 10 of 26

dbroad
Mentor
Mentor

I've forgotten everything I thought I knew about OCS but I think you can use the TRANS function to translate to and from OCS to other coordinate systems if you have the object ename.  I don't know how that would work if  the object wasn't already selected though.

Architect, Registered NC, VA, SC, & GA.
Message 11 of 26

1LandSurveyor
Enthusiast
Enthusiast
That is what i thought as well but i was just making sure...

Thanks.
0 Likes
Message 12 of 26

john.uhden
Mentor
Mentor

Hi, Doug.

I've gotta lotta old code where I used trans quite a bit, but I also have forgotten when to use it.

Anyway, as far as the OP's dilema, I think I would get all kinda technical and ssget all the text candidates and post-process them by determining which of them has the closest center of its bounding box to the pick point, or use my older @Anonymous function to find within which boundingbox the point falls, the latter of the two probably being more reliable.  And if it falls within more than one boundingbox then report and maybe sssetfirst the ones found.

I think there are just too many "holes" and justification variations in text to ssget them reliably with a coordinate filter.

John F. Uhden

0 Likes
Message 13 of 26

1LandSurveyor
Enthusiast
Enthusiast

Here is what i came up 😎

 

 

			(setq FoundOBJ (ssget "_A" (list 
				(cons -4 "<XOR")
					(cons -4 "<AND") (cons 0 "*TEXT") (cons -4 "=,=,*") (cons 11 eInsPt2D)
							(cons -4 "/=") (cons 72 0) (cons -4 "/=") (cons 73 0)  (cons -4 "AND>")
					(cons -4 "<AND") (cons -4 "=,=,*") (cons 10 eInsPt2D) (cons -4 "AND>")
				(cons -4 "XOR>")
				(cons 0 cType) 
				(cons 8 cLayer))))
			

 

 The rest of my routine specifies :

    cType being either *TEXT, POINT or INSERT

    cLayer being a layer filter

   eInsPt2D being a picked WCS point (the insertion point of selected reference entities in my case).

 

Works super great with all types of text justification.

Its only limitation i found is regarding objects with OCS <>WCS as told earlier... but that's fairly rare for Texts

Message 14 of 26

john.uhden
Mentor
Mentor
NICE!!
That's because you are a land surveyor. 👍
You know what they say...
"Old surveyors never die, they just lose their bearings." 🤓
(A Uhden original)

John F. Uhden

Message 15 of 26

dbroad
Mentor
Mentor

Glad you found what you need.  Even though ctype includes points and blocks, however, it will never find them.  As far as optimization goes, the selection might be faster if you put the layer and object type filters first but narrow the object type filter to *text.  In addition, "=" is a very unforgiving attribute.  Also, its only going to find a single text entity since you've narrowed the window to a single point.  I would've preferred to use  (ssget ":S+." (list '(0 . "*text")(cons 8 clayer) pollsibly followed by either (cons 10 einspt2d)) or 

(cons -4 "<XOR")
					(cons -4 "<AND") (cons 0 "*TEXT") (cons -4 "=,=,*") (cons 11 eInsPt2D)
							(cons -4 "/=") (cons 72 0) (cons -4 "/=") (cons 73 0)  (cons -4 "AND>")
					(cons -4 "<AND") (cons -4 "=,=,*") (cons 10 eInsPt2D) (cons -4 "AND>")
				(cons -4 "XOR>")

)) if you really need it.  As long as the text entity is on the screen, it should find the text entity with either the 10 or 11 code.  I'd have to test it a lot to be sure though.   "=" eliminates the forgiveness of the pickbox.

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 16 of 26

dbroad
Mentor
Mentor

You might be right but we don't really know whether the OP cared about whether the text was entirely within the window or not.

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 17 of 26

1LandSurveyor
Enthusiast
Enthusiast

@dbroad wrote:

Glad you found what you need.  Even though ctype includes points and blocks, however, it will never find them.  It does find them. I wonder why you say this. Have I missed something?

 

As far as optimization goes, the selection might be faster if you put the layer and object type filters first but narrow the object type filter to *text.  Thanks for that, i didn't know how to arrange filters for optimization.

 

In addition, "=" is a very unforgiving attribute. You are right, there is no fuzz allowed. You need to know exactly its position first. In my case, my goal was to find the text by pre-selecting a block, another text or a point at the same exact location.

 

Also, its only going to find a single text entity since you've narrowed the window to a single point. Well, from what i tested, a (ssget "A" or "X"...) will find all entities respecting the filters. Multiple objects can have the same exact insertion points and thus will be found...

 

I would've preferred to use  (ssget ":S+." (list '(0 . "*text")(cons 8 clayer) pollsibly followed by either (cons 10 einspt2d)) or 

(cons -4 "<XOR")
					(cons -4 "<AND") (cons 0 "*TEXT") (cons -4 "=,=,*") (cons 11 eInsPt2D)
							(cons -4 "/=") (cons 72 0) (cons -4 "/=") (cons 73 0)  (cons -4 "AND>")
					(cons -4 "<AND") (cons -4 "=,=,*") (cons 10 eInsPt2D) (cons -4 "AND>")
				(cons -4 "XOR>")

)) if you really need it.  As long as the text entity is on the screen, it should find the text entity with either the 10 or 11 code.  I'd have to test it a lot to be sure though.   "=" eliminates the forgiveness of the pickbox. Again, my solution using (ssget "A" ...) would find them all, even not in the screen.


After reading the original post, he was clearly looking for a «non-specific point»... so yes, my solution should be adjusted topermit this by adding even more position filters as the equivalent of a crossing window. (just like the code in your first post).

0 Likes
Message 18 of 26

dbroad
Mentor
Mentor

Sorry. I didn't read the XOR closely enough.  Only the first element of the XOR has a object type filter.

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 19 of 26

john.uhden
Mentor
Mentor
BTW, my idea of using a boundingbox vacuums.

John F. Uhden

0 Likes
Message 20 of 26

Sea-Haven
Mentor
Mentor

My $0.05 I would use a 4 point rectang say around insert pt then ssget "F" PTS 

 

Do this 4 times but add 1st point to end so closes, with relevant x or -x etc

(setq p2 (mapcar '+ p1 (list X Y 0.0)))

 

 

0 Likes