TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: CHulse on March 21, 2019, 03:28:40 PM

Title: MLEADER arrow coordinates
Post by: CHulse on March 21, 2019, 03:28:40 PM
Could anyone share an example of how to access the arrowhead point location (coordinates) for mleaders?

Ultimately, I want to extract the leader coordinates and the text contents, but I don't see how to get to the arrowhead location.

Appreciate any help with this.
Thanks
Title: Re: MLEADER arrow coordinates
Post by: ronjonp on March 21, 2019, 04:18:13 PM
Try something like this for some hints :)
Code: [Select]
(SETQ O (vlax-ename->vla-object (CAR (ENTSEL))))
(vlax-dump-Object O T)
(VLAX-INVOKE O 'GetLeaderLineVertices 0)
Title: Re: MLEADER arrow coordinates
Post by: Lee Mac on March 21, 2019, 05:23:30 PM
Here's another route -
Code - Auto/Visual Lisp: [Select]
  1. (if (setq s (ssget "_+.:E:S" '((0 . "MULTILEADER"))))
  2.     (cdr (assoc 10 (member '(304 . "LEADER_LINE{") (entget (ssname s 0)))))
  3. )
Title: Re: MLEADER arrow coordinates
Post by: CHulse on March 22, 2019, 07:15:21 AM
Thanks guys. I really appreciate the help.
Title: Re: MLEADER arrow coordinates
Post by: CHulse on April 11, 2019, 02:09:13 PM
OK, so I'm a little confused with how this works.

Given 2 different drawings with mleaders-

this worked on one:
Code: [Select]
(vla-getleaderlinevertices obj 0)
but didn't work on the other.
This did:
Code: [Select]
(vla-getleaderlinevertices obj 1)

Help?
Title: Re: MLEADER arrow coordinates
Post by: Dlanor on April 11, 2019, 04:45:52 PM
Typing MLeader on the command lines gives you this :

Specify leader arrowhead location or [leader Landing first/Content first/Options] <Options>:

Default is to construct from arrowhead location to landing then content but you can also opt for Landing first then arrowhead then content

or

Content then construct the leader to the arrowhead (landing location is calculated from content location)

With the default option (vla-getleaderlinevertices obj 0) gets you the arrowhead. With the other options you have to use the (GetVertexCount) method to find out how many vertices there are, and the last one will be the arrowhead

Code - Auto/Visual Lisp: [Select]
  1. (vla-getvertexcount (vlax-ename->vla-object (car (entsel))) 0)

The 0 at the end is the index of the leader, as you can have multiple leaders to a single content. So on a 3 vertex leader the last vertex will be index 2 (indices are zero based)


 

Title: Re: MLEADER arrow coordinates
Post by: Lee Mac on April 11, 2019, 04:51:22 PM
Since a multileader can have multiple leader lines (by using the AIMLEADEREDITADD command), the leaderlineindex argument (the final integer argument) of the getleaderlinevertices method is a zero-based integer index corresponding to the leader line for which you wish to obtain the vertices.

Since leader lines are not re-indexed when a leader line is removed, if you have constructed a multileader with multiple leader lines, and then removed the first leader line constructed (using the AIMLEADEREDITREMOVE command), the remaining leader line will remain at index 1, and invoking the getleaderlinevertices method with a leaderlineindex argument of 0 will result in an error.

I should add that you can obtain a list of valid leader line indexes using the getleaderlineindexes method, and hence, a more robust method of obtaining the leader line vertices (for all leader lines associated with an multileader) could be the following:
Code - Auto/Visual Lisp: [Select]
  1. (defun mleaderlinevertices ( mlr )
  2.     (mapcar '(lambda ( x ) (vlax-invoke mlr 'getleaderlinevertices x)) (vlax-invoke mlr 'getleaderlineindexes 0))
  3. )
Title: Re: MLEADER arrow coordinates
Post by: CHulse on April 12, 2019, 01:16:05 PM
Thanks Lee
using your hint, I've been playing around with this to get the first leader's coordinates:

Code - Auto/Visual Lisp: [Select]
  1. (setq idxa (car(vlax-safearray->list (vlax-variant-value (vla-GetLeaderLineIndexes obj 0))))
  2.          verts (vlax-safearray->list (vlax-variant-value (vla-getleaderlinevertices obj idxa))))
  3.  

This seems to work fine for most, but I still get an error with some leaders, saying "invalid index".


I'm not sure what to check. It seems to happen as you said, if a leader has been removed, and also in a file where the user apparently copy/pasted over and over from another dwg.
 
Is there a way to check for a valid leader that I'm missing?

Title: Re: MLEADER arrow coordinates
Post by: Lee Mac on April 12, 2019, 01:48:02 PM
Why not use the function I provided?
Title: Re: MLEADER arrow coordinates
Post by: CHulse on April 12, 2019, 03:18:24 PM
I did try that and had the same results, unless I wasn't applying it correctly.  I broke it down so I could follow it better. I still struggle with mapcar and lambda.


Here's my testing code:
Code - Auto/Visual Lisp: [Select]
  1. (while (setq en (ssname ss 0))
  2.                 (setq   obj      (vlax-ename->vla-object en) ;convert ename to vla object
  3.                            verts   (mapcar '(lambda ( x ) (vlax-invoke obj 'getleaderlinevertices x)) (vlax-invoke obj 'getleaderlineindexes 0))
  4.                 );_end setq
  5.  
  6.         (princ " verts: " )    
  7.         (princ verts)
  8.         (terpri )
  9.        
  10.         (ssdel en ss)  
  11. );_end while
  12.  
Title: Re: MLEADER arrow coordinates
Post by: CHulse on April 12, 2019, 03:24:12 PM
Here's an example of the mleaders I have. Some work fine and others give the error.
Title: Re: MLEADER arrow coordinates
Post by: Lee Mac on April 13, 2019, 02:41:08 PM
Unless I've overlooked something, there would seem to be insufficient information exposed by the ActiveX properties & methods derived from a Multileader Object to tackle this purely through Visual LISP, for example: the methods getleaderlinevertices, getleaderlineindexes, & getleaderindex all require a leaderlineindex, but there does not appear to be a property or method which yields the available valid leader line indexes which may be supplied to these methods.

As such, I think this task may be easier to tackle through Vanilla AutoLISP since more information is exposed through the DXF data associated with a MULTILEADER entity.

To this end, consider the following function to return the vertices for all leaders associated with a given Multileader entity:
Code - Auto/Visual Lisp: [Select]
  1. (defun LM:mleadervertices ( ent )
  2.     (mapcar '(lambda ( x ) (massoc 10 x))
  3.         (massoc "LEADER_LINE{"
  4.             (cdr
  5.                 (assoc "LEADER{"
  6.                     (cdr
  7.                         (assoc "CONTEXT_DATA{"
  8.                             (parsedxfdata (entget ent))
  9.                         )
  10.                     )
  11.                 )
  12.             )
  13.         )
  14.     )
  15. )
  16. (defun massoc ( k l )
  17.     (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= k (car x))) l))
  18. )
  19. (defun parsedxfdata ( l / foo )
  20.     (defun foo ( / x )
  21.         (setq x (car l)
  22.               l (cdr l)
  23.         )
  24.         (cond
  25.             (   (or (null x) (= "}" (cdr x)))
  26.                 nil
  27.             )
  28.             (   (and (= 'str (type (cdr x))) (wcmatch (cdr x) "*{*"))
  29.                 (cons (cons (cdr x) (foo)) (foo))
  30.             )
  31.             (   (cons x (foo)))
  32.         )
  33.     )
  34.     (foo)
  35. )

Here is a basic program to test the above:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / c e )
  2.     (if
  3.         (and
  4.             (setq e (car (entsel "\nSelect mleader: ")))
  5.             (= "MULTILEADER" (cdr (assoc 0 (entget e))))
  6.             (setq c 1)
  7.         )
  8.         (foreach l (LM:mleadervertices e)
  9.             (foreach v l
  10.                 (entmake (list '(0 . "POINT") (cons 10 v) (cons 62 c)))
  11.             )
  12.             (setq c (1+ (rem c 255)))
  13.         )
  14.     )
  15. )
Title: Re: MLEADER arrow coordinates
Post by: CHulse on April 13, 2019, 03:51:13 PM
Thanks Lee
I'll give this a go on Monday. Much appreciated.