AutoCAD has provided the Overrule .NET API in recent versions. It is the most powerful .NET API so far and can provide almost the custom entity feature that is still only available in the most powerful AutoCAD API, ObjectARX. On the other hand, however, the Overrule API is also the most complex part in the AutoCAD .NET.
Centerline Circle is a common drawing element in the engineering design world but is not provided by AutoCAD natively. Though AutoCAD has some means to control how to show the circle center point, it is far from enough. We presented the centerline circle overrule implementations in some earlier posts.
Previously we added grip point display support to our centerline circles. However, it does not really support grip editing yet. In this post, we will add the support through overriding the MoveGripPointsAt() method to record the moving point and updating the GetGripPoints() method to draw the grip points at their new locations.
Here is a video to demonstrate its behavior first.
Here is the code next.
#region Namespaces
using System;
using System.Text;
using System.Linq;
using System.Xml;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Windows;
using MgdAcApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using MgdAcDocument = Autodesk.AutoCAD.ApplicationServices.Document;
using AcWindowsNS = Autodesk.AutoCAD.Windows;
#endregion
using Autodesk.AutoCAD.GraphicsInterface;
namespace AcadNetAddinWizard_Namespace
{
/// <summary>
/// Features:
/// A derivative from the ObjectOverrule;
/// Being made a singleton to avoid duplicate registrations;
/// UCS being hornored;
/// SetExtensionDictionaryEntryFilter() being called to filter circles with Extension Dictionary Entry;
/// GetGripPoints is overridden to add grips to the center lines of the circles.
/// MoveGripPointsAt is overridden to support grid streching.
/// </summary>
public class CenterlineCircle_GripOverrule1 : GripOverrule
{
private CenterlineCircle_GripOverrule1()
{
//The overrule only works with certain circles marked with the Extension Dictionary Entry.
SetExtensionDictionaryEntryFilter(CenterlineCircle_Gadgets.CLCircle_ID);
}
private static CenterlineCircle_GripOverrule1 mInstance;
public static CenterlineCircle_GripOverrule1 Instance
{
get
{
if (mInstance == null)
mInstance = new CenterlineCircle_GripOverrule1();
return mInstance;
}
}
public override void GetGripPoints(Entity entity, GripDataCollection grips, double curViewUnitSize, int gripSize, Vector3d curViewDir, GetGripPointsFlags bitFlags)
{
base.GetGripPoints(entity, grips, curViewUnitSize, gripSize, curViewDir, bitFlags);
Matrix3d ucs = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem;
Circle cir = entity as Circle;
Point3d cen = cir.Center.TransformBy(ucs.Inverse()); ;
double rad = cir.Radius;
double ratio;
object value = CenterlineCircle_Gadgets.GetDictionaryEntryTypedValue(
CenterlineCircle_Gadgets.GetExtensionDictionaryEntry(cir, CenterlineCircle_Gadgets.CLCircle_ID),
(int)DxfCode.ExtendedDataScale);
if (value == null)
ratio = CenterlineCircle_Gadgets.DefaultRatioLengthToRadius;
else
ratio = Convert.ToDouble(value);
Point3d line1Pt1 = new Point3d(cen.X - rad * ratio, cen.Y, cen.Z).TransformBy(ucs);
Point3d line1Pt2 = new Point3d(cen.X + rad * ratio, cen.Y, cen.Z).TransformBy(ucs);
Point3d line2Pt1 = new Point3d(cen.X, cen.Y - rad * ratio, cen.Z).TransformBy(ucs);
Point3d line2Pt2 = new Point3d(cen.X, cen.Y + rad * ratio, cen.Z).TransformBy(ucs);
CLCircleGripData gd = new CLCircleGripData();
gd.GripPoint = line1Pt1;
grips.Add(gd);
gd = new CLCircleGripData();
gd.GripPoint = line1Pt2;
grips.Add(gd);
gd = new CLCircleGripData();
gd.GripPoint = line2Pt1;
grips.Add(gd);
gd = new CLCircleGripData();
gd.GripPoint = line2Pt2;
grips.Add(gd);
}
public override void MoveGripPointsAt(Entity entity, GripDataCollection grips, Vector3d offset, MoveGripPointsFlags bitFlags)
{
base.MoveGripPointsAt(entity, grips, offset, bitFlags);
if (entity.ObjectId != ObjectId.Null)
{
Circle cir = entity as Circle;
CLCircleGripData gripData = grips[0] as CLCircleGripData;
if (cir != null && gripData != null)
{
CenterlineCircle_Gadgets.UpdateDictionaryEntryTypedValue(
CenterlineCircle_Gadgets.GetSetExtensionDictionaryEntry(entity, CenterlineCircle_Gadgets.CLCircle_ID),
(int)DxfCode.ExtendedDataScale, gripData.GripPoint.Add(offset).DistanceTo(cir.Center) / cir.Radius
);
}
}
}
public override void OnGripStatusChanged(Entity entity, GripStatus status)
{
base.OnGripStatusChanged(entity, status);
}
}
}
Some highlights may look good to help understand the code.
• The centerline circle highlight overrule is derived from the HighlightOverrule API class;
• The centerline circle HighlightOverrule overrule is made a singleton to avoid duplicate registrations or similar issues;
• SetExtensionDictionaryEntryFilter() being called to filter circles with Extension Dictionary Entry;
• MoveGripPointsAt() method has been overridden to to record the new ratio of center line length to circle diameter when grip editing.
• The GetGripPoints() has been enhanced from the earlier version to draw the grip points at their new locations.
• Last but not least, in the Extension Dictionary and XRecord manipulation help methods which are called by the MoveGripPointsAt or GetGripPoints, the regular Transaction generally doesn’t work. Othewise, an eLockViolation exception will come up.
• The OpenCloseTransaction instead had better be used though the direct Open and Close may work too.
Here are the two test commands last.
[CommandMethod("AddCLCircleGripOverrule1")]
public static void AddCLCircleGripOverrule1_Method()
{
CenterlineCircle_Gadgets.RegisterOverrule(typeof(Circle), CenterlineCircle_GripOverrule1.Instance);
}
[CommandMethod("RemoveCLCircleGripOverrule1")]
public static void RemoveCLCircleGripOverrule1_Method()
{
CenterlineCircle_Gadgets.UnregisterOverrule(typeof(Circle), CenterlineCircle_GripOverrule1.Instance);
}
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides various project wizards, item wizards, coders including a Ribbon Creator, and widgets to help program AutoCAD .NET addins.
Posted by: |