How to get start and end points of an existing mleader

How to get start and end points of an existing mleader

dwattersAMXH5
Enthusiast Enthusiast
4,418 Views
34 Replies
Message 1 of 35

How to get start and end points of an existing mleader

dwattersAMXH5
Enthusiast
Enthusiast

hello, 

I am building a lisp to select mleaders and replace them with new mleaders in the same location (changing note in mleader, with data pulled from object data) 
to do this i am going to need to get the start and end point location of the existing leader to plug in to the command to build the new mleader. 
I will also use the start point to populate an nentselp to pull new object data from the object at the point. 

to better clarify - 
i have built a lisp to label a line with an mleader which pulls attributes out of object data.
the best way i can see to automatically update the mleader with new object data (other then doing a find and replace on the text) is to complete delete the original mleader and replace with a new mleader in its exact place which would pull update object data information. 


it will be easy to ssget by the layer because all of these are on a specific layer. and then run a for reach to pull the setq variables i need, delete old one, make new one. i am just not sure about how to get the start and end point data out of the existing mleader so that i can plug those values into the setq variables. 

 

 

can anyone explain the function to do this or at least point me in a direction so that i can do my own searching.

 

thanks for any help in this, 
i can post my starting lisp for the initial mleader if that helps 

0 Likes
Accepted solutions (1)
4,419 Views
34 Replies
Replies (34)
Message 21 of 35

ronjonp
Mentor
Mentor

If it's an xref then you're at the mercy of nentsel(p).  Good luck!

0 Likes
Message 22 of 35

dwattersAMXH5
Enthusiast
Enthusiast

can i still fuzz that? 
similar to : 

(setq pt '(2.0 2.0) fuz 1.0)

;more like

(setq pt1f (pt1) fuz 1.0)

 or will that not help this situation?

i cant even get nentselp to grab the data from the line when not xreffed. 

0 Likes
Message 23 of 35

ronjonp
Mentor
Mentor

If the object within the xref\block contains the 'smart' info then you'll need nentsel(p) .. otherwise you'd need to iterate that block and find the closest item to your pick which gets tricky if your ucs is rotated, the block scale is other than 1 or it's rotated.

Seems like there should be a tool built in to do this?

 

You could try something like this for non-nested items.

(defun _drunkenpick (p fz fltr / a b s)
  ;; This will base the fuzz off of zoom level
  ;; (setq fz (* fz (getvar 'viewsize)))
  (cond	((and p
	      (setq s (ssget "_C"
			     (setq a (mapcar '(lambda (x) (+ x fz)) p))
			     (setq b (mapcar '(lambda (x) (- x fz)) p))
			     fltr
		      )
	      )
	 )
	 (grdraw a b 1)
	 (ssname s 0)
	)
  )
)
(_drunkenpick (getpoint) 1e-1 '((0 . "~MLEADER")))

 

0 Likes
Message 24 of 35

dwattersAMXH5
Enthusiast
Enthusiast

just thinking out loud here - 
we are already using activeX with your code so i wonder if GetSubEntity would work for this possibly in combination with SelectAtPoint
but i dont know if this will return the ename needed for ade_odgettables and ade_odgetfields 
maybe after selecting the item it will be necessary to run entget to pull the ename? 

0 Likes
Message 25 of 35

dwattersAMXH5
Enthusiast
Enthusiast

really the problem comes down to that nentsel returns ename which is required to populate the label, 
nentselp does not return the correct ename.
which causes the rest of my code to look into the wrong ename for the info that is not there. 

in testing nentsel returns entity name xxx-xxxxxxxx while nentselp returns xxx-xxxxxxxx which i believe is the entity name of the block not the nested item in the block. 

0 Likes
Message 26 of 35

dwattersAMXH5
Enthusiast
Enthusiast

sorry it returns with nentsel

entity-name:212 245 104 70 

and 

 

this with nentselp (the block entity name?)

entity-name:212 245 182 20

 

 

(spacing is because the forum was posting them as xxx-xxxxxxxx)

0 Likes
Message 27 of 35

dwattersAMXH5
Enthusiast
Enthusiast

FIGURED IT OUT

that second ename is the mleader. 

so i added a erase to the tester lisp to erase the mleader before picking the point for nentselp 

total duh moment. 

 

 

here's the updated test if you ever have to write anything similar for all your help

 

(defun c:relfq9 (/	   clength    clengthstr data	    en	       fibercnt	  fibercntstr
		fqnid	   fqnidstr   i		 items	    leader-10-list	  lyr
		pt1	   pt2	      pt3	 pts	    source_obj str	  tbl
		wrkord	   wrkordstr
	       )			; <- This is variable localization and it's important
  (setvar "cmdecho" 0)
  (command "clayer" "TEXT_FQNID")
  (prompt "Selecting all Mleaders on layer : \"TEXT_FQNID\"")
  (setq items (ssget "X" (list '(0 . "MULTILEADER") '(8 . "TEXT_FQNID"))))
  (setq i (sslength items))
  (while (> i 0)
    (setq i (1- i))
    (setq en (ssname items i))
    (setq pts (vlax-invoke (vlax-ename->vla-object en) 'getleaderlinevertices 0))
    (setq pt1 (list (car pts) (cadr pts) (caddr pts)))
					; <- First three elements in 'getleaderlinevertices
    (setq pt2 (list (car (setq pts (cdddr pts))) (cadr pts) (caddr pts)))
					; <- Next three elements in 'getleaderlinevertices
		(command "erase" en "")
		(setq source_obj (car (nentselp pt1)))
    (if	(null source_obj)
      (prompt "\nNo source object selected.")
      (progn (setq tbl (ade_odgettables source_obj))
	     (setq fqnid (ade_odgetfield source_obj tbl "FQN_ID" 0))
			 (print source_obj)
			 (print pt1)
			 (print fqnid)
      )					;progn
    )					;if
  )					;while
  (setvar "cmdecho" 1)
  (alert "RELFQ : COMPLETE")
  (princ)
)

thanks!!! 

0 Likes
Message 28 of 35

ronjonp
Mentor
Mentor

Glad you got it sorted!

0 Likes
Message 29 of 35

Kent1Cooper
Consultant
Consultant

@dwattersAMXH5 wrote:

.... to select mleaders and replace them with new mleaders in the same location (changing note in mleader, with data pulled from object data) ....



At the risk of revealing that maybe I don't really understand what you're trying to do, but just based on that wording....

 

Is it really necessary to delete one and build another in the same place with different textual content?  Can't you just replace  the textual content part?  Then you dont need to find the start/end points at all.

 

  (vla-put-TextString (vlax-ename->vla-object MleaderEntityName) "YourNewContent")

 

[however it is among the various possible approaches that you arrive at the entity name and new content]

Kent Cooper, AIA
0 Likes
Message 30 of 35

dwattersAMXH5
Enthusiast
Enthusiast

yea i guess that is a valid option to this routine, 

my knowledge of vla- functions is very shallow, but yea the idea is to update all the info. i would still need pt1 of the mleader to use as a point for nentselp to get the object data i need. i guess we would need to entget to get the entity name of the mleader first but that would probably work too. 

 

the erase and replace was just the simplest way i could work through making it look like the mleader was updated when the object data changed. 

but the erase actually came in handy because nentselp kept grabbing the mleader instead of the nested object. so erasing it before running nentselp solved that. 

the vla route would probably be the better route if you can get around the nentselp issue. 

 

0 Likes
Message 31 of 35

dwattersAMXH5
Enthusiast
Enthusiast

and to better explain the whole thing thats going on here - 

ive built a lisp to get object data from an nentsel 
i make a bunch of setq's with that info and plug that into a mleader 

now if the object data ever changes then i needed a way to update all those labels without going through and doing it manually because we are talking about 1000-10,000 feet per segment with multiple segments. and an mleader being places every 500 ish feet. 


so the lisp in question finds all the mleaders made with that first lisp (they are all placed on a specific layer)  it gets the first and second point. 
deletes the mleader 
it then runs an nentsep with the first point to get all the same object data setq's as the initial lisp. 
then makes a new mleader using pt1 and pt2 and the str of setq's 

that way all the user sees is that the text in the mleader changes when they run the label updater. 

0 Likes
Message 32 of 35

Kent1Cooper
Consultant
Consultant

@dwattersAMXH5 wrote:

....
but the erase actually came in handy because nentselp kept grabbing the mleader instead of the nested object. so erasing it before running nentselp solved that. 

the vla route would probably be the better route if you can get around the nentselp issue. 


 

You could get the entity name of the Mleader, get only its arrowhead location, (entdel) it, do the (nentselp) thing using that arrowhead location, and then [here's the tricky part] use (entdel) on the Mleader's entity name again, which will bring it back!

Kent Cooper, AIA
0 Likes
Message 33 of 35

dwattersAMXH5
Enthusiast
Enthusiast

Ohhhh nice. 

yea thats seems like a much better work around especially if you were using the ename of any specific mleader for anything else, as my method doesnt keep the same entity. 

0 Likes
Message 34 of 35

ronjonp
Mentor
Mentor

@dwattersAMXH5 wrote:

...
if you can get around the nentselp issue. 

 


This may fix that problem:

(setq items (ssget "X" (list '(0 . "MULTILEADER") '(8 . "TEXT_FQNID"))))
(command "_.draworder" items "" "Back")

 I also agree that you should just update the contents rather than creating a new mleader.

(vla-put-textstring (vlax-ename->vla-object en) "YourString")
0 Likes
Message 35 of 35

dwattersAMXH5
Enthusiast
Enthusiast

thanks for the insight and all the help guys! 
Yea i will probably re-write it in a few days when i get the time. 

0 Likes