November 2014

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            










« Moving text in an AutoCAD block using .NET – Part 1 | Main | My week at AU 2013 »

December 05, 2013

Moving text in an AutoCAD block using .NET – Part 2

I was planning to post about Autodesk University 2013 today, but things have just been too hectic. I have a 3-hour layover in Heathrow on the journey home – which starts this evening – so I’ll try to use that to post a summary of this year’s AU as experienced by yours truly.

In the last post we saw some code to move an entity – any entity, with text as the primary requirement – in a block.

Here’s a version of the C# code that shows the entity as it’s being jigged across the screen to its new position. The interesting part of this, in many ways, is the transformations that are needed pre- and post-jig to make sure the entity is under the cursor (the same transformation matrices calculated from the nested containers in the last post).

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.Runtime;

 

namespace Textformations

{

  public class DisplacementJig : EntityJig

  {

    private Point3d _pos;

    private Point3d _loc;

 

    public DisplacementJig(Entity ent, Point3d basePt)

      : base(ent)

    {

      _loc = basePt;

    }

 

    protected override bool Update()

    {

      var disp = _pos - _loc;

      _loc = _pos;

      var mat = Matrix3d.Displacement(disp);

      Entity.TransformBy(mat);

      return true;

    }

 

    protected override SamplerStatus Sampler(JigPrompts prompts)

    {

      var opts =

        new JigPromptPointOptions("\nSelect displacement");

      opts.BasePoint = _pos;

      opts.UserInputControls =

        UserInputControls.NoZeroResponseAccepted;

 

      var ppr = prompts.AcquirePoint(opts);

      if (_pos == ppr.Value)

        return SamplerStatus.NoChange;

 

      _pos = ppr.Value;

 

      return SamplerStatus.OK;

    }

  }

 

  public class Commands2

  {

    [CommandMethod("MTIBJIG")]

    public static void MoveTextInBlock()

    {

      var doc = Application.DocumentManager.MdiActiveDocument;

      var db = doc.Database;

      var ed = doc.Editor;

 

      // Start by getting the text (or other) object in the block

 

      var pneo =

        new PromptNestedEntityOptions("\nSelect text inside block");

      var pner = ed.GetNestedEntity(pneo);

 

      if (pner.Status != PromptStatus.OK)

        return;

 

      var selId = pner.ObjectId;

 

      // Start a transaction to access the object

 

      var oc = selId.ObjectClass;

      if (

        !oc.IsDerivedFrom(

          RXClass.GetClass(typeof(DBText))

        ) &&

        !oc.IsDerivedFrom(

          RXClass.GetClass(typeof(MText))

        )

      )

      {

        // Isn't a text object - ask whether we continue

 

        ed.WriteMessage(

          "\nObject is not text, it is a {0}.", oc.Name

        );

 

        var pko =

          new PromptKeywordOptions(

            "\nDo you want to continue? [Yes/No]", "Yes No"

          );

        pko.AppendKeywordsToMessage = true;

        pko.AllowNone = true;

        pko.Keywords.Default = "No";

 

        var pr = ed.GetKeywords(pko);

        if (

          pr.Status != PromptStatus.OK || pr.StringResult == "No"

        )

          return;

      }

 

      // Start a transaction to modify the object

 

      using (var tr = doc.TransactionManager.StartTransaction())

      {

        // Unless we get a block reference container, use the

        // identity matrix as the block transform

 

        var brMat = Matrix3d.Identity;

 

        // Get the containers around the nested entity

 

        var conts = pner.GetContainers();

        foreach (var brId in conts)

        {

          var br =

            tr.GetObject(brId, OpenMode.ForRead) as BlockReference;

          if (br != null)

          {

            brMat = brMat.PreMultiplyBy(br.BlockTransform);

          }

        }

 

        // Transform the entity

 

        var ent = (Entity)tr.GetObject(selId, OpenMode.ForWrite);

 

        // Before we run the jig, transform the object by the

        // aggregate transform of the containers

 

        ent.TransformBy(brMat);

 

        // Run the jig to displace the object

 

        var dj = new DisplacementJig(ent, pner.PickedPoint);

        var pr = ed.Drag(dj);

        if (pr.Status == PromptStatus.OK)

        {

          // We can transform the entity back, now (at least in

          // terms of the containers: the displacement remains)

 

          ent.TransformBy(brMat.Inverse());

 

          // Open each of the containers and set a property so that

        // they each get regenerated

 

          foreach (var id in conts)

          {

            var ent2 = tr.GetObject(id, OpenMode.ForWrite) as Entity;

            if (ent2 != null)

            {

              // We might also have called this method:

              // ent2.RecordGraphicsModified(true);

              // but setting a property works better with undo

 

              ent2.Visible = ent2.Visible;

            }

          }

 

          tr.Commit();

        }

      }

    }

  }

}

Here’s the new MTIBJIG command in action:

MTIBJIG

blog comments powered by Disqus

Feed/Share

10 Random Posts