Kean Walmsley


  • About the Author
    Kean on Google+

July 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 31    








« Win a free Premier Pass for AU Virtual 2010 worth $139! | Main | Mac Attack »

September 27, 2010

Revolving an AutoCAD solid using .NET

Thanks to Philippe Leefsma, from our DevTech team in Europe, for providing the code for this post. Philippe kindly based his code on that provided in this previous post, which made it especially easy for me to format for posting. Thanks, Philippe! :-)

In the post linked to above we saw some code defining a SAP (SweepAlongPath) command. This post extends that to implement a complementary RAA (RevolveAroundAxis) command. Philippe’s original code asked the user for a line to define the axis of revolution. I generalised the code slightly to accept a curve: as we’re only using the vector between the start and endpoints to define the axis of revolution, this will work. This has the advantage of now working with polylines that cleanly define an axis (i.e. with a single straight segment) but has the disadvantage (or perhaps we can call it a dubious advantage :-) of working with other types of curve that do not (such as arcs, circles and multiline segment polylines). I could have coded more defensively to disallow certain axes being used, but ultimately the code runs just fine, and works very well according to the GIGO principle. :-)

Here’s the C# code:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.Geometry;

using System;

 

namespace SolidCreation

{

  public class Commands

  {

    [CommandMethod("SAP")]

    public void SweepAlongPath()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

 

      // Ask the user to select a region to extrude

 

      PromptEntityOptions peo1 =

        new PromptEntityOptions(

          "\nSelect profile or curve to sweep: "

        );

 

      peo1.SetRejectMessage(

        "\nEntity must be a region, curve or planar surface."

      );

      peo1.AddAllowedClass(

        typeof(Region), false);

      peo1.AddAllowedClass(

        typeof(Curve), false);

      peo1.AddAllowedClass(

        typeof(PlaneSurface), false);

 

      PromptEntityResult per =

        ed.GetEntity(peo1);

 

      if (per.Status != PromptStatus.OK)

        return;

 

      ObjectId regId = per.ObjectId;

 

      // Ask the user to select an extrusion path

 

      PromptEntityOptions peo2 =

        new PromptEntityOptions(

          "\nSelect path along which to sweep: "

        );

 

      peo2.SetRejectMessage(

        "\nEntity must be a curve."

      );

      peo2.AddAllowedClass(

        typeof(Curve), false);

 

      per = ed.GetEntity(peo2);

 

      if (per.Status != PromptStatus.OK)

        return;

 

      ObjectId splId = per.ObjectId;

 

      PromptKeywordOptions pko =

        new PromptKeywordOptions(

          "\nSweep a solid or a surface?"

        );

      pko.AllowNone = true;

      pko.Keywords.Add("SOlid");

      pko.Keywords.Add("SUrface");

      pko.Keywords.Default = "SOlid";

 

      PromptResult pkr =

        ed.GetKeywords(pko);

 

      bool createSolid = (pkr.StringResult == "SOlid");

 

      if (pkr.Status != PromptStatus.OK)

        return;

 

      // Now let's create our swept surface

 

      Transaction tr =

        db.TransactionManager.StartTransaction();

      using (tr)

      {

        try

        {

          Entity sweepEnt =

            tr.GetObject(regId, OpenMode.ForRead) as Entity;

 

          Curve pathEnt =

            tr.GetObject(splId, OpenMode.ForRead) as Curve;

 

          if (sweepEnt == null || pathEnt == null)

          {

            ed.WriteMessage(

              "\nProblem opening the selected entities."

            );

            return;

          }

 

          // We use a builder object to create

          // our SweepOptions

 

          SweepOptionsBuilder sob =

            new SweepOptionsBuilder();

 

          // Align the entity to sweep to the path

 

          sob.Align =

            SweepOptionsAlignOption.AlignSweepEntityToPath;

 

          // The base point is the start of the path

 

          sob.BasePoint = pathEnt.StartPoint;

 

          // The profile will rotate to follow the path

 

          sob.Bank = true;

 

          // Now generate the solid or surface...

 

          Entity ent;

 

          if (createSolid)

          {

            Solid3d sol = new Solid3d();

 

            sol.RecordHistory = true;

 

            sol.CreateSweptSolid(

              sweepEnt,

              pathEnt,

              sob.ToSweepOptions()

            );

 

            ent = sol;

          }

          else

          {

            SweptSurface ss = new SweptSurface();

 

            ss.CreateSweptSurface(

              sweepEnt,

              pathEnt,

              sob.ToSweepOptions()

            );

 

            ent = ss;

          }

 

          // ... and add it to the modelspace

 

          BlockTable bt =

            (BlockTable)tr.GetObject(

              db.BlockTableId,

              OpenMode.ForRead

            );

 

          BlockTableRecord ms =

            (BlockTableRecord)tr.GetObject(

              bt[BlockTableRecord.ModelSpace],

              OpenMode.ForWrite

            );

 

          ms.AppendEntity(ent);

          tr.AddNewlyCreatedDBObject(ent, true);

 

          tr.Commit();

        }

        catch

        { }

      }

    }

 

    [CommandMethod("RAA")]

    public void RevolveAroundAxis()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

 

      // Ask the user to select a region to revolve

 

      PromptEntityOptions peo1 =

        new PromptEntityOptions(

          "\nSelect profile or curve to revolve: "

        );

      peo1.SetRejectMessage(

        "\nEntity must be a region, curve or planar surface."

      );

      peo1.AddAllowedClass(typeof(Region), false);

      peo1.AddAllowedClass(typeof(Curve), false);

      peo1.AddAllowedClass(typeof(PlaneSurface), false);

 

      PromptEntityResult per1 = ed.GetEntity(peo1);

 

      if (per1.Status != PromptStatus.OK)

        return;

 

      // Ask the user to select an axis of revolution

 

      PromptEntityOptions peo2 =

        new PromptEntityOptions(

          "\nSelect axis of revolution: "

        );

      peo2.SetRejectMessage(

        "\nEntity defining axis must be a curve."

      );

      peo2.AddAllowedClass(typeof(Curve), false);

 

      PromptEntityResult per2 = ed.GetEntity(peo2);

 

      if (per2.Status != PromptStatus.OK)

        return;

 

      Transaction tr =

        db.TransactionManager.StartTransaction();

      using (tr)

      {

        Entity prof =

          (Entity)tr.GetObject(per1.ObjectId, OpenMode.ForRead);

 

        Curve cur =

          (Curve)tr.GetObject(per2.ObjectId, OpenMode.ForRead);

 

        // Set up the options for our revolution

 

        RevolveOptionsBuilder rob = new RevolveOptionsBuilder();

        rob.CloseToAxis = false;

        rob.DraftAngle = 0;

        rob.TwistAngle = 0;

 

        // Create our solid and revolve our profile

 

        Solid3d sol = new Solid3d();

 

        sol.RecordHistory = true;

 

        sol.CreateRevolvedSolid(

          prof,

          cur.StartPoint,

          cur.EndPoint.GetAsVector() - cur.StartPoint.GetAsVector(),

          2 * Math.PI, // Go all the way round

          0,

          rob.ToRevolveOptions()

        );

 

        // We'll add the solid to modelspace

 

        BlockTable bt =

          (BlockTable)tr.GetObject(

            db.BlockTableId,

            OpenMode.ForRead

          );

        BlockTableRecord ms =

          (BlockTableRecord)tr.GetObject(

            bt[BlockTableRecord.ModelSpace],

            OpenMode.ForWrite

          );

 

        ms.AppendEntity(sol);

        tr.AddNewlyCreatedDBObject(sol, true);

        tr.Commit();

      }

    }

  }

}

Now let’s see the code in action. We’ll start by creating a simple closed polyline for our profile and a line defining our axis of revolution:

Our profile and axis of revolution

Calling the RAA command, we can select these objects to generate our solid:

Our revolved solid

And here are the results in a 3D view with the “conceptual” Visual Style set:Our revolution in 3D

Vive la Révolution! :-)

blog comments powered by Disqus

10 Random Posts