Author Topic: How to get and apply the correct MLeader vertiex??  (Read 5436 times)

0 Members and 1 Guest are viewing this topic.

sonny3g

  • Newt
  • Posts: 27
How to get and apply the correct MLeader vertiex??
« on: December 11, 2017, 06:36:32 AM »
Been working on this for a week now and I am very close to being done, just need a little help figuring out how to get the correct vertex points to use on the new mleader.  When we do an approval drawing, all of this information is required, but when we do the installation drawings we only need the first line of text.  Any help is appreciated.

 

Attached are three screen shots, the first is a sample of what I am starting with.  The starting point is four (most drawings have many more than four) mleaders with multiple lines of text each.  The second image show the result of running my program to create a single text line mleader.  And the last image is what I really need it to look like when the program is done.  Here is my code so far:

Code - C#: [Select]
  1. [CommandMethod("TagMotor")]
  2. public static void DOSE_TagMotor()
  3. {
  4.     // Get the current document and database
  5.     Document acDoc = Application.DocumentManager.MdiActiveDocument;
  6.     Database acCurDb = acDoc.Database;
  7.  
  8.     // Get the current document editor
  9.     Editor acDocEd = Application.DocumentManager.MdiActiveDocument.Editor;
  10.  
  11.     // Create a TypedValue array to define the filter criteria
  12.     TypedValue[] ulTypValAr = new TypedValue[4];
  13.     ulTypValAr.SetValue(new TypedValue((int)DxfCode.Operator, "<and"), 0);
  14.     ulTypValAr.SetValue(new TypedValue((int)DxfCode.Start, "MULTILEADER"), 1);
  15.     ulTypValAr.SetValue(new TypedValue((int)DxfCode.LayerName, "*_UNIT"), 2);
  16.     ulTypValAr.SetValue(new TypedValue((int)DxfCode.Operator, "and>"), 3);
  17.  
  18.     // Assign the filter criteria to a SelectionFilter oject
  19.     SelectionFilter ulSelFtr = new SelectionFilter(ulTypValAr);
  20.  
  21.     // Request for objects to be selected in the drawing area
  22.     PromptSelectionResult ulSSPromptRes;
  23.     ulSSPromptRes = acDocEd.GetSelection(ulSelFtr);
  24.  
  25.     if (ulSSPromptRes.Status == PromptStatus.OK)
  26.     {
  27.         SelectionSet ulSSet = ulSSPromptRes.Value;
  28.         // set MLeader to TGW MOTORS
  29.         SetTGWMotorMLeader(acDoc, acCurDb);
  30.  
  31.         // Start iteration transaction
  32.         using (Transaction ulTrans = acCurDb.TransactionManager.StartTransaction())
  33.         {
  34.             // Open block table for read
  35.             BlockTable ulBlkTbl;
  36.             ulBlkTbl = ulTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
  37.  
  38.             // Open the block table record Model space for read
  39.             BlockTableRecord ulBlkTblRec;
  40.             ulBlkTblRec = ulTrans.GetObject(ulBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
  41.  
  42.             // Step through each MLeader in selection set
  43.             foreach (ObjectId ulMlId in ulSSet.GetObjectIds())
  44.             {
  45.                 MLeader ulMldr = ulTrans.GetObject(ulMlId, OpenMode.ForRead) as MLeader;
  46.  
  47.                 if (ulMldr.HasContent())
  48.                 {
  49.                     // Check if MLeader has MText
  50.                     if (ulMldr.ContentType == ContentType.MTextContent)
  51.                     {
  52.                         String ulLayNam;
  53.                         String UnitLabel;
  54.                         ulLayNam = ulMldr.Layer.ToString();
  55.                         int pos = 0;
  56.                         UnitLabel = ulMldr.MText.Contents.ToString();
  57.                         if (UnitLabel.Contains('\n'))
  58.                         {
  59.                             for (int n = 0; n < UnitLabel.Length; n++)
  60.                             {
  61.                                 if (UnitLabel.ElementAt(n) == '\n')
  62.                                 {
  63.                                     pos = n;
  64.                                     break;
  65.                                 }
  66.                             }// end for unitlabel length
  67.                         }// end if "\n" exists
  68.                         else
  69.                         {
  70.                             pos = UnitLabel.Length;
  71.                         }// end if "\n" does not exist
  72.  
  73.                         using (Transaction lTrans = acCurDb.TransactionManager.StartTransaction())
  74.                         {
  75.                             string MtrLayNam;
  76.                                 if (ulLayNam.Contains("_TAG_UNIT") == true)
  77.                             {
  78.                                 MtrLayNam = ulLayNam.Replace("_TAG_UNIT", "_TAG_MTR");
  79.                             }// end if unit layer contains _TAG
  80.                             else
  81.                             {
  82.                                 MtrLayNam = ulLayNam.Replace("_UNIT", "_TAG_MTR");
  83.                             }// end if unit layer does NOT contain _TAG
  84.                             LayerTable lTbl;
  85.                             lTbl = lTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForRead) as LayerTable;
  86.  
  87.                             if (lTbl.Has(MtrLayNam) == true)
  88.                             {
  89.                                 acCurDb.Clayer = lTbl[MtrLayNam];
  90.                                 }// end if layer exists
  91.                             else
  92.                             {
  93.                                 LayerTableRecord lRec;
  94.                                 lTbl.UpgradeOpen();
  95.                                 lRec = lTrans.GetObject(lTbl[ulLayNam], OpenMode.ForRead).Clone() as LayerTableRecord;
  96.                                 lRec.Name = MtrLayNam;
  97.                                 lTbl.Add(lRec);
  98.                                 lTrans.AddNewlyCreatedDBObject(lRec, true);
  99.                                 acCurDb.Clayer = lTbl[MtrLayNam];
  100.                             }// end clone layer if _Tag_Motor layer does not exist
  101.                             lTrans.Commit();
  102.                         }// end lTrans
  103.  
  104.                         // Getting and setting MLeader MText contents
  105.                         MText MtrTag = new MText();
  106.                         string tag = UnitLabel.Remove(pos, UnitLabel.Count() - pos);
  107.                         MtrTag.Contents = tag;
  108.  
  109.                         Point3d ulPt1;
  110.                         Point3d ulPt2;
  111.                         ulPt1 = ulMldr.GetFirstVertex(0);
  112.                         ulPt2 = ulMldr.GetLastVertex(0);
  113.  
  114.                         ulBlkTblRec.UpgradeOpen();
  115.  
  116.                         MLeader mtrLead = new MLeader();
  117.                         int i = mtrLead.AddLeader();
  118.                         mtrLead.MText = MtrTag;
  119.                         mtrLead.TextAlignmentType = TextAlignmentType.LeftAlignment;
  120.                         mtrLead.TextAttachmentType = TextAttachmentType.AttachmentMiddle;
  121.                         mtrLead.AddLeaderLine(i);
  122.                         mtrLead.AddFirstVertex(i, new Point3d(ulPt1[0], ulPt1[1], 0));
  123.                         mtrLead.AddLastVertex(i, new Point3d(ulPt2[0], ulPt2[1], 0));
  124.  
  125.                         ulBlkTblRec.AppendEntity(mtrLead);
  126.                         ulTrans.AddNewlyCreatedDBObject(mtrLead, true);
  127.                         //}// end lTrans
  128.                         //ulTrans.Commit();
  129.                     }// end if multileader has MText content
  130.                 }// end if multileader has content
  131.                 //ulTrans.Commit();
  132.             }// end foreach object in selection set
  133.             ulTrans.Commit();
  134.         }// end ulTrans
  135.     }// end if selection prompt ok
  136. }// end DOSE_TagMotor


EDIT (John): Added code tags for better readability.
« Last Edit: January 09, 2018, 08:50:27 AM by John Kaul (Se7en) »

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: How to get and apply the correct MLeader vertiex??
« Reply #1 on: December 11, 2017, 12:40:19 PM »
Why create a whole other leader? Just Clone() the first leader and give it a new MText object.
Revit 2019, AMEP 2019 64bit Win 10

sonny3g

  • Newt
  • Posts: 27
Re: How to get and apply the correct MLeader vertiex??
« Reply #2 on: December 12, 2017, 06:34:54 AM »
We were trying to make the new leader style slightly different from the original.  And, being new to programming in C#, I hadn't thought of trying to clone the original leader and supplying a new mtext object.  I will see if I can figure that out as it sounds like it might be a lot less code.

Thanks for the suggestion.

sonny3g

  • Newt
  • Posts: 27
Re: How to get and apply the correct MLeader vertiex??
« Reply #3 on: December 12, 2017, 10:48:43 AM »
Almost there, cloning the MLeader is definitely the way to go like you suggested MC.  But, I still need to change the MLeader style and move the cloned MLeader to a different layer.  This part is proving to be difficult for me.  Replacing the MText object was simple, but I cannot figure out how I change the layer for the new MLeader object or its MultiLeaderStyle before committing the transaction.

Can you help me out?

Thanks.

Atook

  • Swamp Rat
  • Posts: 1027
  • AKA Tim
Re: How to get and apply the correct MLeader vertiex??
« Reply #4 on: December 12, 2017, 01:50:37 PM »
Hey sonny, some reading for you.

Not tested or compiled, but maybe it'll give you some ideas.

Code - C#: [Select]
  1. MLeader mLady = oldMLeader.clone();
  2. mLady.MLeaderStyle=GetMLeaderStyleID("Frilly");
  3. mLady.Layer="Parfait";
  4.  
  5. /// <summary>
  6. /// Checks if the MLeader Style definition is in the active drawing
  7. /// </summary>
  8. /// <param name="styleName">Name of the MLeader style.</param>
  9. /// <returns>ObjectID of MLeader style, ObjectId.Null on error</returns>
  10. public static ObjectId GetMLeaderStyleID(string styleName)
  11. {
  12.   ObjectId styleId = ObjectId.Null;
  13.   Document acDoc = Application.DocumentManager.MdiActiveDocument;
  14.   Database acCurDb = acDoc.Database;
  15.   using (Transaction acTr = acCurDb.TransactionManager.StartTransaction())
  16.   {
  17.     DBDictionary mlDictionary = (DBDictionary)acTr.GetObject(Active.Database.MLeaderStyleDictionaryId, OpenMode.ForRead);
  18.     if (mlDictionary.Contains(styleName))
  19.     {
  20.       styleId = mlDictionary.GetAt(styleName);
  21.       acTr.Commit();
  22.     }
  23.   }
  24.   return styleId;
  25. }
  26.  
  27.  

hope that helps.

sonny3g

  • Newt
  • Posts: 27
Re: How to get and apply the correct MLeader vertiex??
« Reply #5 on: December 12, 2017, 02:42:52 PM »
Thanks Atook!! Got it working just the way I needed it to.


sonny3g

  • Newt
  • Posts: 27
Re: How to get and apply the correct MLeader vertiex??
« Reply #6 on: December 28, 2017, 12:10:06 PM »
And I spoke too soon.  The program does create my new MLeader the way I want it, but, and this is a show stopper, when I save the drawing and open it later, the new MLeaders are messed up as shown in the attachment.  Any ideas on why it goes haywire when the drawing is saved?

Thanks


Atook

  • Swamp Rat
  • Posts: 1027
  • AKA Tim
Re: How to get and apply the correct MLeader vertiex??
« Reply #7 on: December 28, 2017, 12:51:40 PM »
I'm not sure about the why of it, though I suspect the Autodesk .NET implementation of MLeaders has some bugs in it. If not 'bugs' per se, it acts differently than I'd expect. And when I use the MgdDbg Inspector tool on MLeaders, it crashes out.

I would pay attention to setting the properties of the MText object, things like .TextStyle, .TextHeight, and possibly the .Attachment properties.

Good luck.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: How to get and apply the correct MLeader vertiex??
« Reply #8 on: December 28, 2017, 02:27:12 PM »
I'm not sure about the why of it, though I suspect the Autodesk .NET implementation of MLeaders has some bugs in it. If not 'bugs' per se, it acts differently than I'd expect. And when I use the MgdDbg Inspector tool on MLeaders, it crashes out.

I would pay attention to setting the properties of the MText object, things like .TextStyle, .TextHeight, and possibly the .Attachment properties.

Good luck.
Take a look at this post
https://www.theswamp.org/index.php?topic=41576.msg467316#msg467316

Atook

  • Swamp Rat
  • Posts: 1027
  • AKA Tim
Re: How to get and apply the correct MLeader vertiex??
« Reply #9 on: December 28, 2017, 05:10:20 PM »
...https://www.theswamp.org/index.php?topic=41576.msg467316#msg467316
Thanks Jeff, surprised they haven't updated their source code yet. I'll take a look later and maybe make a pull request. I've been contemplating trying to get a copy working for Bricscad too.

sonny3g

  • Newt
  • Posts: 27
Re: How to get and apply the correct MLeader vertiex??
« Reply #10 on: January 04, 2018, 05:14:04 AM »
Atook, you hit the nail on the head.  Once I included the .TextHeight parameter in the program it worked correctly.  Thanks for the heads up.

sonny3g

  • Newt
  • Posts: 27
Re: How to get and apply the correct MLeader vertiex??
« Reply #11 on: January 08, 2018, 02:28:49 PM »
I just cannot figure out what I am doing wrong.  I am getting the new MLeader with the desired contents, but I cannot get it to accept the textheight of 1/8", it always assigns 0 to the text height.  This despite having the new MLeaderstyle already existing with the text height set to 1/8".  Below is my code, if anyone can help me keep from completely losing my mind over this I will be very grateful

Code - C#: [Select]
  1. using (Transaction nmlTrans = acCurDb.TransactionManager.StartTransaction())
  2. {
  3.     // Getting and setting MLeader MText contents
  4.     MText MtrTag = new MText();
  5.     MtrTag.Annotative = AnnotativeStates.True;
  6.     string tag = UnitLabel.Remove(pos, UnitLabel.Count() - pos);
  7.     MtrTag.Contents = tag;
  8.     ulBlkTblRec.UpgradeOpen();
  9.  
  10.     DBDictionary mlDictionary = (DBDictionary)nmlTrans.GetObject(acCurDb.MLeaderStyleDictionaryId, OpenMode.ForRead);
  11.     MLeader mtrLead = new MLeader();
  12.     mtrLead = ulMldr.Clone() as MLeader
  13.     mtrLead.MLeaderStyle = mlDictionary.GetAt("TGW MOTORS");
  14.     mtrLead.Annotative = AnnotativeStates.True;
  15.     mtrLead.MText = MtrTag;
  16.     mtrLead.MText.Location = ulMldr.MText.Location;
  17.     mtrLead.MText.Attachment = ulMldr.MText.Attachment;
  18.     mtrLead.MText.TextHeight = ulMldr.MText.TextHeight;
  19.     mtrLead.Layer = MtrLayNam;
  20.  
  21.     ulBlkTblRec.AppendEntity(mtrLead);
  22.     nmlTrans.AddNewlyCreatedDBObject(mtrLead, true);
  23.     nmlTrans.Commit();
  24. }// end nmlTrans


EDIT (John): Added code tags for better readability.
« Last Edit: January 09, 2018, 08:48:18 AM by John Kaul (Se7en) »

Jeff H

  • Needs a day job
  • Posts: 6144
Re: How to get and apply the correct MLeader vertiex??
« Reply #12 on: January 08, 2018, 03:07:24 PM »

sonny3g

  • Newt
  • Posts: 27
Re: How to get and apply the correct MLeader vertiex??
« Reply #13 on: January 09, 2018, 05:47:28 AM »
I have been working on this off and on now for over a month and I cannot get this to work.  I have received many suggestions and pointers and I am still not getting something right.  I simply don't know where to turn next on this.  This is what I have for code, all of it.  Also included what the results are.

Thanks for all the help you guys have been giving me and I apologize that I am too dense to quite get it.

sonny3g

  • Newt
  • Posts: 27
Re: How to get and apply the correct MLeader vertiex??
« Reply #14 on: January 09, 2018, 10:15:11 AM »
I don't know how I stumbled upon this, but, I was trying to assign the textheight to the mtext entity instead of the mleader.  When I assign the height to mleader.textheight instead of mleader.mtext.textheight, it seems to work and the properties show the correct text height for paper space.

Now for more testing just to make sure...