December 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      










« AutoCAD .NET Training DevTV Session 2: User Interaction – User Input | Main | Sweeping an AutoCAD solid from Kinect-captured geometry »

May 16, 2011

Jigging an AutoCAD circle from three points in arbitrary 3D space using .NET

I suspect that many of you who have worked with point clouds will have come across this issue: the standard CIRCLE command in AutoCAD will create the circle on the plane of the active User Coordinate System (UCS), even when the circle is defined by three points on its circumference. This behaviour is probably fine for the majority of 2D drafting activities, but if you want to create circles from a point cloud – by selecting points from its perimeter using the Node object snap – then it’s less than ideal.

The code in today’s post implements a very simple jig that creates the circle in 3D, irrespective of the current UCS. It works especially well when picking points from point clouds, which is something I’ll be showing in a future post.

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 EntityJigging

{

  public class ThreePtCircleJig : EntityJig

  {

    Point3d _first, _second, _third;

 

    public ThreePtCircleJig(

      Point3d first, Point3d second

    )

      : base(new Circle())

    {

      _first = first;

      _second = second;

    }

 

    protected override SamplerStatus Sampler(

      JigPrompts jp

    )

    {

      // We acquire a single 3D point

 

      JigPromptPointOptions jo =

        new JigPromptPointOptions(

          "\nSelect third point"

        );

      jo.UserInputControls =

        UserInputControls.Accept3dCoordinates;

 

      PromptPointResult ppr = jp.AcquirePoint(jo);

 

      if (ppr.Status == PromptStatus.OK)

      {

        // Check whether it's basically unchanged

 

        if (

          _third.DistanceTo(ppr.Value) <

          Tolerance.Global.EqualPoint

        )

        {

          return SamplerStatus.NoChange;

        }

 

        // Otherwise just set the jig's state

 

        _third = ppr.Value;

        return SamplerStatus.OK;

      }

      return SamplerStatus.Cancel;

    }

 

    protected override bool Update()

    {

      // Create a temporary CircularArc3d by three points

      // and use it to create our Circle

 

      CircularArc3d ca =

        new CircularArc3d(_first, _second, _third);

 

      Circle cir = Entity as Circle;

      cir.Center = ca.Center;

      cir.Normal = ca.Normal;

      cir.Radius = ca.Radius;

 

      return true;

    }

 

    public Entity GetEntity()

    {

      return Entity;

    }

  }

 

  public class Commands

  {

    [CommandMethod("ADNPLUGINS", "3PCIR", CommandFlags.Modal)]

    public void CreateCircle()

    {

      Document doc =

        Autodesk.AutoCAD.ApplicationServices.

          Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;

 

      // Ask the user to select the first two points

      // outside the jig

 

      PromptPointOptions ppo =

        new PromptPointOptions(

          "\nSelect first point"

        );

      ppo.AllowNone = false;

 

      PromptPointResult ppr = ed.GetPoint(ppo);

 

      if (ppr.Status != PromptStatus.OK)

        return;

 

      Point3d first = ppr.Value;

 

      ppo.Message = "\nSelect second point";

 

      ppr = ed.GetPoint(ppo);

 

      if (ppr.Status != PromptStatus.OK)

        return;

 

      Point3d second = ppr.Value;

 

      // Pass the points into the jig

 

      ThreePtCircleJig cj =

        new ThreePtCircleJig(first, second);

 

      // Then execute it

 

      PromptResult pr = ed.Drag(cj);

 

      if (pr.Status != PromptStatus.OK)

        return;

 

      Transaction tr =

        doc.TransactionManager.StartTransaction();

      using (tr)

      {

        // Add our circle to the current space

 

        BlockTableRecord btr =

          (BlockTableRecord)tr.GetObject(

            doc.Database.CurrentSpaceId,

            OpenMode.ForWrite

          );

 

        Entity ent = cj.GetEntity();

        btr.AppendEntity(ent);

        tr.AddNewlyCreatedDBObject(ent, true);

 

        tr.Commit();

      }

    }

  }

} 

The 3PCIR command isn’t especially exciting, in action. If you’re interested, you can see it in my next YouTube video about integrating AutoCAD with Kinect (which I’ll post a link to before long).

blog comments powered by Disqus

Feed/Share

10 Random Posts