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    








« Gluing a point to an AutoCAD curve using overrules from .NET – Part 1 | Main | AU 2009 YouTube contest »

August 26, 2009

Gluing a point to an AutoCAD curve using overrules from .NET – Part 2

In the last post we looked at some code to create a point on a curve, and make sure it stays on that curve when edited.

In this post we’re extending that code (albeit slightly) to work with a network of curves: the idea is that any curve which has a point created on it becomes a candidate for any point to snap onto as it moves around. This could clearly be extended to provided a better way of specifying the curves forming the network, of course.

Here’s the updated C# code, with the modified/new lines in red (the full source file is available here):

    1 using Autodesk.AutoCAD.ApplicationServices;

    2 using Autodesk.AutoCAD.DatabaseServices;

    3 using Autodesk.AutoCAD.EditorInput;

    4 using Autodesk.AutoCAD.Geometry;

    5 using Autodesk.AutoCAD.Runtime;

    6 using System.Collections.Generic;

    7 

    8 namespace PointOnCurveTest

    9 {

   10   public class PtTransOverrule : TransformOverrule

   11   {

   12     // A static pointer to our overrule instance

   13 

   14     static public PtTransOverrule theOverrule =

   15       new PtTransOverrule();

   16 

   17     // A list of the curves that have had points

   18     // attached to

   19 

   20     static internal List<ObjectId> _curves =

   21       new List<ObjectId>();

   22 

   23     // A flag to indicate whether we're overruling

   24 

   25     static bool overruling = false;

   26 

   27     public PtTransOverrule() { }

   28 

   29     // Out primary overruled function

   30 

   31     public override void TransformBy(Entity e, Matrix3d mat)

   32     {

   33       // We only care about points

   34 

   35       DBPoint pt = e as DBPoint;

   36       if (pt != null)

   37       {

   38         Database db = HostApplicationServices.WorkingDatabase;

   39 

   40         // Work through the curves to find the closest to our

   41         // transformed point

   42 

   43         double min = 0.0;

   44         Point3d bestPt = Point3d.Origin;

   45         bool first = true;

   46 

   47         // We're using an Open/Close transaction, to avoid

   48         // problems with us using transactions in an event

   49         // handler

   50 

   51         OpenCloseTransaction tr =

   52           db.TransactionManager.StartOpenCloseTransaction();

   53         using (tr)

   54         {

   55           foreach (ObjectId curId in _curves)

   56           {

   57             DBObject obj =

   58               tr.GetObject(curId, OpenMode.ForRead);

   59             Curve cur = obj as Curve;

   60             if (cur != null)

   61             {

   62               Point3d ptLoc =

   63                 pt.Position.TransformBy(mat);

   64               Point3d ptOnCurve =

   65                 cur.GetClosestPointTo(ptLoc, false);

   66               Vector3d dist = ptOnCurve - ptLoc;

   67 

   68               if (first || dist.Length < min)

   69               {

   70                 first = false;

   71                 min = dist.Length;

   72                 bestPt = ptOnCurve;

   73               }

   74             }

   75           }

   76           pt.Position = bestPt;

   77         }

   78       }

   79     }

   80 

   81     [CommandMethod("POC")]

   82     public void CreatePointOnCurve()

   83     {

   84       Document doc =

   85         Application.DocumentManager.MdiActiveDocument;

   86       Database db = doc.Database;

   87       Editor ed = doc.Editor;

   88 

   89       // Ask the user to select a curve

   90 

   91       PromptEntityOptions opts =

   92         new PromptEntityOptions(

   93           "\nSelect curve at the point to create: "

   94         );

   95       opts.SetRejectMessage(

   96         "\nEntity must be a curve."

   97       );

   98       opts.AddAllowedClass(typeof(Curve), false);

   99 

  100       PromptEntityResult per = ed.GetEntity(opts);

  101 

  102       ObjectId curId = per.ObjectId;

  103       if (curId != ObjectId.Null)

  104       {

  105         // Let's make sure we'll be able to see our point

  106 

  107         db.Pdmode = 97;  // square with a circle

  108         db.Pdsize = -10; // relative to the viewport size

  109 

  110         Transaction tr =

  111           doc.TransactionManager.StartTransaction();

  112         using (tr)

  113         {

  114           DBObject obj =

  115             tr.GetObject(curId, OpenMode.ForRead);

  116           Curve cur = obj as Curve;

  117           if (cur != null)

  118           {

  119             // Our initial point should be the closest point

  120             // on the curve to the one picked

  121 

  122             Point3d pos =

  123               cur.GetClosestPointTo(per.PickedPoint, false);

  124             DBPoint pt = new DBPoint(pos);

  125 

  126             // Add it to the same space as the curve

  127 

  128             BlockTableRecord btr =

  129               (BlockTableRecord)tr.GetObject(

  130                 cur.BlockId,

  131                 OpenMode.ForWrite

  132               );

  133             ObjectId ptId = btr.AppendEntity(pt);

  134             tr.AddNewlyCreatedDBObject(pt, true);

  135           }

  136           tr.Commit();

  137 

  138           // And add the curve to our central list

  139 

  140           _curves.Add(curId);

  141         }

  142 

  143         // Turn on the transform overrule if it isn't already

  144 

  145         if (!overruling)

  146         {

  147           ObjectOverrule.AddOverrule(

  148             RXClass.GetClass(typeof(DBPoint)),

  149             PtTransOverrule.theOverrule,

  150             true

  151           );

  152           overruling = true;

  153           TransformOverrule.Overruling = true;

  154         }

  155       }

  156     }

  157   }

  158 }

Now after having run our POC command to add points to a number of curves – effectively adding them to the “network” – we can grip-move a point, and should another curve in the network be closer, the point being edited will snap across to that one:

Moving a point between curves

TrackBack

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

Listed below are links to weblogs that reference Gluing a point to an AutoCAD curve using overrules from .NET – Part 2:

blog comments powered by Disqus

10 Random Posts