AutoCAD .NET API provides two concrete Jig classes for us to jig different entities in different circumstances, EntityJig and DrawJig. EntityJig is to jig a specific entity as its name indicates and the DrawJig is to jig anything that has graphics to draw, which can be a single entity, a group of entities, or something that is not available natively in AutoCAD.
We have demonstrated jigging a circle by both its center and radius using the EntityJig class previously. In this article, let us add the keyword support for collecting a color such as Red, Green and Blue for the circle during its jigging.
Here is the test command for this circle jig we are going to talk about:
[CommandMethod("TestEntityJigger1")]
public static void TestEntityJigger1_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
if (EntityJigger1.Jig())
{
ed.WriteMessage("\nA circle has been successfully jigged and added to the database.\n");
}
else
{
ed.WriteMessage("\nIt failed to jig and add a circle to the database.\n");
}
}
Here is how the circle jig behaves this time in AutoCAD after the test command runs, a center is input, some color is chosen, and its radius is jigging:
The following outputs may be there in the AutoCAD command line window:
Command:
TESTENTITYJIGGER1
Circle center [Red/Green/Blue]: r
Circle center [Red/Green/Blue]:
Circle radius [Red/Green/Blue]: g
Circle radius [Red/Green/Blue]: b
Circle radius [Red/Green/Blue]: g
Circle radius [Red/Green/Blue]:
A circle has been successfully jigged and added to the database.
By the way, cancellations/escapes by users will gracefully be handled by the jig as usual.
Here is the core source:
#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.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
namespace AcadNetAddinWizard_Namespace
{
public class EntityJigger1 : EntityJig
{
#region Fields
private Circle mEntity;
public int mCurJigFactorNumber = 1;
private Point3d mCenter = new Point3d(); // Factor #1
private double mRadius = 0.0001; // Factor #2 : It is critical to set it as none zero to avoid the degeneration problem.
private int mColorIndex = -1; // Factor #3 : Also a flag to indicate if a ColorIndex is input.
#endregion
#region Constructors
public EntityJigger1(Entity ent) : base(ent)
{
mEntity = ent as Circle;
mEntity.Center = mCenter;
mEntity.Radius = mRadius;
}
#endregion
#region Overrides
protected override bool Update()
{
if (mColorIndex >= 0 && mColorIndex <= 256)
{
(Entity as Circle).ColorIndex = mColorIndex;
mColorIndex = -1;
return true;
}
switch (mCurJigFactorNumber)
{
case 1:
(Entity as Circle).Center = mCenter;
break;
case 2:
(Entity as Circle).Radius = mRadius;
break;
default:
return false;
}
return true;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
switch (mCurJigFactorNumber)
{
case 1:
JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nCircle center:");
prOptions1.Keywords.Add("Red");
prOptions1.Keywords.Add("Green");
prOptions1.Keywords.Add("Blue");
PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1);
if (prResult1.Status == PromptStatus.Keyword)
{
switch (prResult1.StringResult)
{
case "Red":
mColorIndex = 1;
break;
case "Green":
mColorIndex = 3;
break;
case "Blue":
mColorIndex = 5;
break;
default:
mColorIndex = -1;
break;
}
return SamplerStatus.OK;
}
if (prResult1.Status != PromptStatus.OK) return SamplerStatus.Cancel;
if (prResult1.Value.Equals(mCenter))
{
return SamplerStatus.NoChange;
}
else
{
mCenter = prResult1.Value;
return SamplerStatus.OK;
}
case 2:
JigPromptDistanceOptions prOptions2 = new JigPromptDistanceOptions("\nCircle radius:");
prOptions2.Keywords.Add("Red");
prOptions2.Keywords.Add("Green");
prOptions2.Keywords.Add("Blue");
prOptions2.BasePoint = mCenter;
PromptDoubleResult prResult2 = prompts.AcquireDistance(prOptions2);
if (prResult2.Status == PromptStatus.Keyword)
{
switch (prResult2.StringResult)
{
case "Red":
mColorIndex = 1;
break;
case "Green":
mColorIndex = 3;
break;
case "Blue":
mColorIndex = 5;
break;
default:
mColorIndex = -1;
break;
}
return SamplerStatus.OK;
}
if (prResult2.Status != PromptStatus.OK) return SamplerStatus.Cancel;
if (prResult2.Value.Equals(mRadius))
{
return SamplerStatus.NoChange;
}
else
{
if ( prResult2.Value < 0.0001) // To avoid the degeneration problem!
{
return SamplerStatus.NoChange;
}
else
{
mRadius = prResult2.Value;
return SamplerStatus.OK;
}
}
default:
break;
}
return SamplerStatus.OK;
}
#endregion
#region Method to Call
public static bool Jig()
{
try
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
EntityJigger1 jigger = new EntityJigger1(new Circle());
PromptResult pr;
do {
pr = ed.Drag(jigger);
} while ( pr.Status == PromptStatus.Keyword ||
(pr.Status == PromptStatus.OK && jigger.mCurJigFactorNumber++ <= 2) );
if (pr.Status == PromptStatus.OK)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
btr.AppendEntity(jigger.Entity);
tr.AddNewlyCreatedDBObject(jigger.Entity, true);
tr.Commit();
}
}
else
{
return false;
}
return true;
}
catch
{
return false;
}
}
#endregion
}
}
A few highlights about the code may be helpful:
• An entity type needs to be specified in the EntityJig derivative, as Circle here.
• The Sampler() override is to acquire input for the center and the radius in a certain order.
• If the input is the same as the stored variable, we’d better return SamplerStatus.NoChange to avoid unnecessary flashing; if not, return SamplerStatus.OK.
• The keywords can be added easily through the Keywords collection of the JigPromptPointOptions or other similar prompt options objects.
• The keyword input can be checked from the Status property of the PromptPointResult or similar and the keyword value can be retrieved from the StringResult property of the same PromptResult object.
• Please do not forget to handle the cancel/escape circumstance as demonstrated.
• The Update() override is to update the center and the radius properties of the circle in the same order as set in the Sampler().
• The Editor.Draw() is the power to fire the jig. If two properties need to be set, the jig needs to be fired off twice. That is why a while loop is used.
• The while loop also needs to think about the PromptStatus.Keyword case of the PromptResult after each Jig Drag.
• Only after the jig succeeds should the circle be added to the database to avoid database corruption.
• The last but important, please make sure the radius of the circle either in memory or database resident is never zero, otherwise a degeneration exception would come up.
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides a coder, Entity Jigger, to help us create entity jig code automatically, quickly and reliably.
Recent Comments