Kean Walmsley

July 2009

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Twitter Updates

    follow me on Twitter



    « Creating a spline-segment multileader in AutoCAD using .NET | Main | AU Unplugged session on AutoCAD development »

    September 06, 2007

    Creating an AutoCAD multileader spraying out from central text using .NET

    Some more fun with multileaders... this post shows some code that adds multiple leader lines to a multileader/MLeader, each of them "spraying" out from the central text. We ask the user for the central point and the location of the first leader along with the number of leader lines to "spray". These lines then get created at evenly spaced angles around from this initial location.

    I can't think of anything immediately useful about this technique, other than it was fun to write the code and it shows how to add multiple leader lines. It also generates some fun results. :-)

    Here's the C# code:

    using Autodesk.AutoCAD.Runtime;

    using Autodesk.AutoCAD.ApplicationServices;

    using Autodesk.AutoCAD.DatabaseServices;

    using Autodesk.AutoCAD.EditorInput;

    using Autodesk.AutoCAD.Geometry;


    namespace DimensionLibrary

    {

      public class DimensionCommands

      {

        [CommandMethod("spray")]

        static public void SprayMultiLeader()

        {

          Document doc =

            Application.DocumentManager.MdiActiveDocument;

          Editor ed = doc.Editor;

          Database db = doc.Database;


          // Get the start point of the leader

          PromptPointResult ppr =

            ed.GetPoint(

              "\nSpecify position of text: "

            );

          if (ppr.Status != PromptStatus.OK)

            return;

          Point3d startPt = ppr.Value;


          // Get the end point of the leader

          PromptPointOptions ppo =

            new PromptPointOptions(

              "\nSpecify first arrowhead location: "

            );

          ppo.BasePoint = startPt;

          ppo.UseBasePoint = true;

          ppr = ed.GetPoint(ppo);

          if (ppr.Status != PromptStatus.OK)

            return;

          Point3d endPt = ppr.Value;


          // Get the number of leader lines

          // to "spray" out from the center

          PromptIntegerOptions pio =

            new PromptIntegerOptions(

              "\nNumber of leader lines <1>: "

            );

          pio.AllowNone = true;

          pio.AllowZero = false;

          PromptIntegerResult pir =

            ed.GetInteger(pio);

          int numLines;

          if (pir.Status == PromptStatus.None)

            numLines = 1;

          else

          {

            if (pir.Status != PromptStatus.OK)

              return;

            else

              numLines = pir.Value;

          }


          Transaction tr =

            db.TransactionManager.StartTransaction();

          using (tr)

          {

            try

            {

              BlockTable bt =

                (BlockTable)tr.GetObject(

                  db.BlockTableId,

                  OpenMode.ForRead

                );

              BlockTableRecord btr =

                (BlockTableRecord)tr.GetObject(

                  bt[BlockTableRecord.ModelSpace],

                  OpenMode.ForWrite

                );


              // Create the MLeader

              MLeader mld = new MLeader();

              for(int i=0; i < numLines; i++)

              {

                // Each leader line sprays out

                // at a different angle

                Vector3d vec = endPt - startPt;

                vec =

                  vec.RotateBy(

                    i * 2 * System.Math.PI / numLines,

                    mld.Normal

                  );

                Point3d landPt = startPt + vec;

                int ldNum = mld.AddLeader();

                int lnNum = mld.AddLeaderLine(ldNum);

                mld.AddFirstVertex(lnNum, landPt);

                mld.AddLastVertex(lnNum, startPt);

              }

              mld.LeaderLineType =

                LeaderType.SplineLeader;


              // Create the MText

              MText mt = new MText();

              mt.Contents =

                "Multileader with " +

                numLines.ToString() +

                " \nradial splines";


              mld.ContentType =

                ContentType.MTextContent;

              mld.MText = mt;

              mld.TextLocation = startPt;


              // Add the MLeader

              btr.AppendEntity(mld);

              tr.AddNewlyCreatedDBObject(mld, true);


              tr.Commit();

            }

            catch (Exception ex)

            {

              ed.WriteMessage("\nException: " + ex.Message);

              // Would also happen automatically

              // if we didn't commit

              tr.Abort();

            }

          }

        }

      }

    }

    Here's a 7-line multileader created by the SPRAY command:

    Mleader_multiple_segment_spline

    TrackBack

    TrackBack URL for this entry:
    http://www.typepad.com/services/trackback/6a00d83452464869e200e54ed80bc88833

    Listed below are links to weblogs that reference Creating an AutoCAD multileader spraying out from central text using .NET:

    Comments

    Is there any chance of making the MLeader associated with the entity using ObjectARX .NET 2008? Thanks!

    -Gagan

    Gagan,

    I haven't looked into whether MLeaders can be associative to geometry. If it's not available as core functionality, you could certain implement your own associativity using events in .NET (probably a comibination of Database.ObjectModified and DocumentManager.DocumentLockModeWillChange).

    I'd suggest posting your question to the discussion groups or asking the ADN team (if you're a member).

    Regards,

    Kean

    Whenever I attempt to run your code in Civil-3D 2009, all of the leaders come out of the left side of the MLeader.

    If I select and drag the MLeader slightly, it will "recalculate" itself, and display as shown in your screen shot, with leaders coming out both sides of the text. But if I simply run the code, all leaders emanate from the left side of the text only.

    If I run your code in Civil-3D 2008, I get the same results as you, with leaders coming out both sides of the text. However, with C3D 2009, they only come out the left side.

    Any idea why, or how to get around this issue? I'd like to create an MLeader to the left of a point, and have the leader come out the right side of the text, but I can't seem to manage it in 2009.

    I have tried using the default acad.dwt template, and also "Starting from Scratch", just to try to eliminate any possible issues with the template, and I get the same result.

    This appears to be something different in base AutoCAD 2009 (and therefore the products built upon it).

    Adding this line of code forces a recalculation of the MLeader (I put it just before the line that commits the transaction):

    mld.MoveMLeader(new Vector3d(), MoveType.MoveAllPoints);

    It essentially moves all the points of the MLeader through a zero-length vector. So it does nothing, but the geometry gets corrected.

    I hope this helps you,

    Kean

    Thanks! That worked.

    Verify your Comment

    Previewing your Comment

    This is only a preview. Your comment has not yet been posted.

    Working...
    Your comment could not be posted. Error type:
    Your comment has been posted. Post another comment

    The letters and numbers you entered did not match the image. Please try again.

    As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

    Having trouble reading this image? View an alternate.

    Working...

    Post a comment

    Feed & Share

    Search