September 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        








« Tired of not being able to NETUNLOAD from AutoCAD? "Edit and Continue" to the rescue! | Main | An interview with John Walker - Part 4 »

October 01, 2008

Mirroring AutoCAD entities using .NET

The code used as the basis for this post was from a recent response sent out by Philippe Leefsma, from our European DevTech team. Thanks, Philippe!

It's very common to want to manipulate an entity programmatically in AutoCAD, and often the best way to do so is to "transform" it. The technique is very straightforward: you create a transformation matrix using the static members of the Matrix3d class (Displacement(), Rotation(), Scaling(), Mirroring(), or the possibly less commonly needed AlignCoordinateSystem(), Projection(), PlaneToWorld() and WorldToPlane()), you make sure your entity is open for write, and then simply pass the matrix into the entity's TransformBy() method.

And that's really all there is to it. The below code demonstrates a very simplistic usage of TransformBy(): we want to make a mirrored copy of an entity. We use the Clone() method to generate a "shallow" copy of the original entity - which means that you may have less success with more complex entities that require "deep" cloning - and we then apply a mirror transformation to the clone (having asked the user to specify the mirror line). Please don't take this as a definitive approach to mirroring - there are probably lots of cases that it doesn't handle, in fact I've just seen a follow-up response from Philippe covering the case of mirroring text, which I'll no doubt steal for a future post :-) - but this should give an overall indication of how to use matrices to transform entities.

Here's the C# code:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.Runtime;


namespace EntityTransformation

{

  public class Commands

  {

    [CommandMethod("MENT")]

    static public void MirrorEntity()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;


      // Prompt for the entity to mirror


      PromptEntityOptions peo =

        new PromptEntityOptions(

          "\nSelect an entity:"

        );

      PromptEntityResult per =

        ed.GetEntity(peo);


      if (per.Status != PromptStatus.OK)

        return;


      // Get the points defining the mirror line


      PromptPointOptions ppo =

        new PromptPointOptions(

          "\nSelect first point of mirror line:"

        );


      PromptPointResult ppr =

        ed.GetPoint(ppo);


      if (ppr.Status != PromptStatus.OK)

        return;


      Point3d pt1 = ppr.Value;


      ppo.BasePoint = pt1;

      ppo.UseBasePoint = true;

      ppo.Message =

        "\nSelect second point of mirror line:";


      ppr = ed.GetPoint(ppo);

      if (ppr.Status != PromptStatus.OK)

        return;


      Point3d pt2 = ppr.Value;


      // Create the mirror line and the transformation matrix


      Line3d ml =

        new Line3d(pt1, pt2);


      MirrorEntity(doc.Database, per.ObjectId, ml, false);

    }


    // Helper function to mirror an entity


    private static void MirrorEntity(

      Database db,

      ObjectId id,

      Line3d line,

      bool erase

    )

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;


      Matrix3d mm =

        Matrix3d.Mirroring(line);


      Transaction tr =

        db.TransactionManager.StartTransaction();

      using (tr)

      {

        // Get the entity to mirror


        Entity ent =

          tr.GetObject(

            id,

            OpenMode.ForRead

          ) as Entity;


        // Clone it


        Entity me = ent.Clone() as Entity;


        // Apply the mirror transformation


        me.TransformBy(mm);


        // Add mirrored entity to the database


        BlockTable bt =

          (BlockTable)tr.GetObject(

            db.BlockTableId,

            OpenMode.ForRead

          );

        BlockTableRecord btr =

          (BlockTableRecord)tr.GetObject(

            bt[BlockTableRecord.ModelSpace],

            OpenMode.ForWrite

          );


        btr.AppendEntity(me);

        tr.AddNewlyCreatedDBObject(me, true);


        if (erase)

        {

          // Finally erase the original entity (if needed)


          ent.UpgradeOpen();

          ent.Erase();

        }

        tr.Commit();

      }

    }

  }

}

TrackBack

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

Listed below are links to weblogs that reference Mirroring AutoCAD entities using .NET:

blog comments powered by Disqus

Feed/Share

10 Random Posts