TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: cadpoobah on January 03, 2018, 04:21:03 PM

Title: "Rotating" MLeader block content to horizontal
Post by: cadpoobah on January 03, 2018, 04:21:03 PM
We have some drawings that have been rotated, along with all their MLeaders (some containing text, some containing blocks). These all need re-oriented to be horizontal again.

Fixing those with text is not a huge deal. It can be done manually via the Properties palette (there's a "Rotation" option). I was also able to write a function that will select all the MLeaders and change the rotation to 0 via the vla-put-TextRotation (https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/AutoCAD-ActiveX/files/GUID-EB9C76B1-4CCD-4080-BB04-30A496DA4E09-htm.html) function.

The MLeaders with blocks is another issue, though. There is no similar vla- function that I've found. There is a DXF group code (46) that returns the block's rotation. Changing it "appears" to work, but if the grip-edit the leader afterward, it still acts as if the MLeader is rotated (the new landing goes haywire).

Ideally, I'd like to create a TOrient (https://knowledge.autodesk.com/support/autocad/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-Core/files/GUID-3A9CCCD9-7B1D-4C83-944C-2D66F5FF32DF-htm.html)-style program that would work for MLeaders, rotating them to be horizontal. For that matter, I'd even be satisfied if the function deleted the existing MLeader and simply recreated it using the same points.

Any thoughts or suggestions would be appreciated!
Title: Re: "Rotating" MLeader block content to horizontal
Post by: Lee Mac on January 03, 2018, 04:50:02 PM
How about using the ROTATE command / vla-rotate method to rotate the MLeader about its arrowhead point by the angle of the text rotation?
Title: Re: "Rotating" MLeader block content to horizontal
Post by: cadpoobah on January 03, 2018, 05:33:26 PM
That's a possibility, but the MLeader itself could potentially end up being rotated back over top of other geometry that it didn't overlap previously.

I'd rather the leader's basic geometry stay how it is and only the content (the block) be reoriented, similar to how changing the Rotation property in the palette only changes the text's orientation, leaving the leader geometry alone (except for the landing).
Title: Re: "Rotating" MLeader block content to horizontal
Post by: ChrisCarlson on January 04, 2018, 12:51:48 PM
Simple fix would be to simply have a vertical and horizontal version of the block tied to a mleader style. Then simply change the desired mleader style.
Title: Re: "Rotating" MLeader block content to horizontal
Post by: cadpoobah on January 04, 2018, 01:24:11 PM
Simple fix would be to simply have a vertical and horizontal version of the block tied to a mleader style. Then simply change the desired mleader style.

Yes, if things were only rotated in 90 deg increments. *sigh*
Title: Re: "Rotating" MLeader block content to horizontal
Post by: ChrisCarlson on January 05, 2018, 09:13:00 AM
If your desire is to have 360° of rotation of full function within the mleader, I don't see that being possible.
Title: Re: "Rotating" MLeader block content to horizontal
Post by: cadpoobah on January 05, 2018, 12:17:01 PM
Not exactly, @Master_Shake. I'm not expecting "grip-edit" style functionality, where you can simply click on the MLeader's block and rotate it to any angle (although, that could be pretty handy!).

Rather, if geometry (including MLeaders) gets rotated, I would like a way to re-orient the MLeader content (whether text or block) to its proper, readable orientation (again, think TOrient (https://knowledge.autodesk.com/support/autocad/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-Core/files/GUID-3A9CCCD9-7B1D-4C83-944C-2D66F5FF32DF-htm.html)). As mentioned, this is possible for MLeaders with text, but for for MLeaders with blocks, the only option is to delete and recreate it.
 (https://i.pinimg.com/236x/5b/d3/0e/5bd30e9ece87c56a7d263866ece0b3b2--time-time-business-cards.jpg)

I just want functionality that is already possible with MLeaders containing text; via the TextRotation (https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/AutoCAD-ActiveX/files/GUID-EB9C76B1-4CCD-4080-BB04-30A496DA4E09-htm.html) function. I guess expecting consistent behavior across all AutoCAD objects is a little too much to ask.  :tickedoff:

Title: Re: "Rotating" MLeader block content to horizontal
Post by: ronjonp on January 05, 2018, 12:22:56 PM
Why is the drawing getting rotated? It seems that the "correct" way to do this is DVIEW TWIST ?
Title: Re: "Rotating" MLeader block content to horizontal
Post by: cadpoobah on January 05, 2018, 12:31:48 PM
Why is the drawing getting rotated? It seems that the "correct" way to do this is DVIEW TWIST ?

Agreed. More precisely, the geometry has been rotated, not the drawing.
Title: Re: "Rotating" MLeader block content to horizontal
Post by: ronjonp on January 05, 2018, 12:50:10 PM
Maybe post a drawing with before and after results.
Title: Re: "Rotating" MLeader block content to horizontal
Post by: cadpoobah on January 05, 2018, 02:08:22 PM
Maybe post a drawing with before and after results.

Posted. Shown (left) is an office layout in it's typical orientation. But it's not uncommon to need that layout oriented completely differently (right), requiring manual MLeader cleanup afterward.

Now, expand that cleanup effort to other areas of the drawing (potentially the entire drawing) and you get an idea of why a TOrient-style program would be extremely helpful.
Title: Re: "Rotating" MLeader block content to horizontal
Post by: ChrisCarlson on January 05, 2018, 02:24:18 PM
Some searching yield something that kind of works

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/block-mleader-rotate-an-existing-mleader/m-p/7665762/highlight/true#M363381
Title: Re: "Rotating" MLeader block content to horizontal
Post by: ronjonp on January 05, 2018, 02:30:22 PM
If this is always an issue, is there a possibility to change your leaders to have mtext content? Then this would be VERY easy :).
Title: Re: "Rotating" MLeader block content to horizontal
Post by: cadpoobah on January 05, 2018, 03:00:58 PM
Some searching yield something that kind of works

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/block-mleader-rotate-an-existing-mleader/m-p/7665762/highlight/true#M363381

Yea, I'm tracking that thread as well. SonicSSV's solution is getting closer. Will definitely share a link if there are any breakthroughs.
Title: Re: "Rotating" MLeader block content to horizontal
Post by: cadpoobah on January 05, 2018, 03:02:22 PM
If this is always an issue, is there a possibility to change your leaders to have mtext content? Then this would be VERY easy :).

Agreed. Client wants their cute little ovals.  :hahanot:
Title: Re: "Rotating" MLeader block content to horizontal
Post by: ronjonp on January 05, 2018, 03:06:18 PM
Well it was worth a try :) . Seems like recreating the mleader would be the easiest for this then, but you'd still have some manual cleanup.
Title: Re: "Rotating" MLeader block content to horizontal
Post by: ChrisCarlson on January 05, 2018, 04:21:55 PM
Could you make your static blocks into dynamic block with a text rotation and "fudge" the mleaders?
Title: Re: "Rotating" MLeader block content to horizontal
Post by: Grrr1337 on January 05, 2018, 06:38:22 PM
Well it was worth a try :) . Seems like recreating the mleader would be the easiest for this then, but you'd still have some manual cleanup.

I thought the same and decided to try that out. :)
And saw the few problems that occur (aside from the obvious manual cleanup):
Heres the sloppy code as a starting point (try it on cadpoobah's dwg to see/understand the listed problems) :
Code - Auto/Visual Lisp: [Select]
  1. (defun C:test ( / MleaderBlockAtts doc spc SS i o n L )
  2.  
  3.   ; _$ (MleaderBlockAtts (vlax-ename->vla-object (car (entsel)))) -> (("EQNOMISC" 1060 "") ("EQNO" 1059 "N0802"))
  4.   (defun MleaderBlockAtts ( mld / id L )
  5.     (and
  6.       (eq 'VLA-OBJECT (type mld)) (member (vla-get-ObjectName mld) '("AcDbMLeader" "AcDbLeader"))
  7.       (eq (vla-get-ContentType mld) acBlockContent)
  8.       (vlax-for x (vla-Item (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))) (vla-get-ContentBlockName mld))
  9.         (and
  10.           (eq (vla-get-ObjectName x) "AcDbAttributeDefinition") (setq id (vla-get-ObjectID x))
  11.           (setq L (cons (list (vla-get-TagString x) id (vla-GetBlockAttributeValue mld id)) L))
  12.         )
  13.       ); vlax-for
  14.     ); and
  15.     L
  16.   ); defun MleaderBlockAtts
  17.  
  18.   (and
  19.     (princ "\nSelect multileaders: ")
  20.     (setq SS (ssget "_:L-I" '((0 . "MULTILEADER"))))
  21.     (repeat (setq i (sslength SS))
  22.       (and
  23.         (setq o (vlax-ename->vla-object (ssname SS (setq i (1- i)))))
  24.         (setq n (vla-get-LeaderCount o))
  25.         (setq L (MleaderBlockAtts o))
  26.         (cond
  27.           ( (zerop n) ; Mleader that doesn't contains any leaders - lets create a block reference
  28.             (
  29.               (lambda ( / _dist _cen b atts att ll1 ll2 ur1 ur2 )
  30.                 (setq _dist (lambda (p1 p2) (apply 'distance (mapcar 'vlax-safearray->list (list p1 p2)))))
  31.                 (setq _cen (lambda ( pts ) (vlax-3D-point (apply 'mapcar (cons '(lambda (a b) (/ (+ a b) 2.)) (mapcar 'vlax-safearray->list pts))))))
  32.                 (vla-GetBoundingBox o 'll1 'ur1)
  33.                 (setq b (vlax-invoke spc 'InsertBlock '(0. 0. 0.) (vla-get-ContentBlockName o) 1 1 1 0.))
  34.                 (vla-GetBoundingBox b 'll2 'ur2)
  35.                 (vlax-invoke b 'ScaleEntity '(0. 0. 0.) (/ (_dist ll1 ur1) (_dist ll2 ur2))) ; <- THIS IS NOT CORRECT, I KNOW (but its close to the result)
  36.                 (vla-GetBoundingBox b 'll2 'ur2)
  37.                 (vla-Move b (_cen (list ll2 ur2)) (_cen (list ll1 ur1)))
  38.                 (setq atts (mapcar (function (lambda (x) (cons (vla-get-TagString x) x))) (vlax-invoke b 'GetAttributes)))
  39.                 (foreach x L
  40.                   (and
  41.                     (setq att (cdr (assoc (car x) atts)))
  42.                     (vla-put-TextString att (last x))
  43.                   )
  44.                 ); foreach
  45.                 (vla-put-Layer b (vla-get-Layer o))
  46.                 (vla-Delete o)
  47.               ); lambda
  48.             )
  49.           )
  50.           ( (>= n 1) ; Standard Mleader that contains 1+ leaders
  51.             (
  52.               (lambda ( / tmp new )
  53.                 (and
  54.                   (not (vl-catch-all-error-p (setq tmp (vl-catch-all-apply 'vla-GetLeaderLineVertices (list o 0)))))
  55.                   (setq new (vla-AddMLeader spc tmp 0))
  56.                   (progn
  57.                     (foreach x '(ArrowheadSize ArrowheadType ContentBlockName ContentType StyleName Layer LeaderType BlockConnectionType BlockScale)
  58.                       (vlax-put new x (vlax-get o x))
  59.                     ); foreach
  60.                     (foreach x L (apply 'vla-SetBlockAttributeValue (cons new (cdr x))) )
  61.                     (vla-Delete o)
  62.                   ); progn
  63.                 ); and
  64.               ); lambda
  65.             )
  66.           )
  67.         ); cond
  68.       ); and
  69.     ); repeat
  70.   ); and
  71.   (princ)
  72. ); defun

So this is what I tried to solve problem #2 - but it creates only one 'leader' for the multileader object:
Code - Auto/Visual Lisp: [Select]
  1.   (setq n (vla-get-LeaderCount o))
  2.   (not (vl-catch-all-error-p (setq tmp (vl-catch-all-apply 'vla-GetLeaderLineVertices (list o 0))))) ; 'tmp' - the initial safearray
  3.   (setq new (vla-AddMLeader spc tmp 0)) ; use 'tmp' to create the mleader (since its required)
  4.   (progn
  5.     (vla-RemoveLeader new 0) ; remove the only leader we added to the mleader, so we won't mess up the indexes
  6.     (repeat n
  7.       (setq n (1- n))
  8.       (setq tmp (vla-AddLeader new))
  9.       (vla-AddLeaderLine new tmp (vla-GetLeaderLineVertices o n))
  10.     ); repeat
  11.   ); progn
  12. ); and