AutoCAD .NET API provides two concrete Jig classes for us to jig different entities in different circumstances, EntityJig and DrawJig. EntityJig is primarily used 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.
In this article, let us see how to jig multiple line segments using the same core code as we introduced a bit earlier about jigging a single line by its points. Here is the test command for the multi-line jig we are going to talk about:
[CommandMethod("TestEntityJigger12")]
public static void TestEntityJigger12_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
if (LineJigger.Jig())
{
ed.WriteMessage("\nA line segment has been successfully jigged and added to the database.\n");
}
else
{
ed.WriteMessage("\nIt failed to jig and add a line segment to the database.\n");
}
}
Here is how the multi-line jig behaves in AutoCAD when a few segments have already been jigged:
As can be seen, the single command can jig multiple line segments without any interruptions and the UCS is hornored.
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 LineJigger : EntityJig
{
#region Fields
public Point3d mEndPoint = new Point3d(); // Factor #1
#endregion
#region Constructors
public LineJigger(Line ent)
: base(ent)
{
}
#endregion
#region Overrides
protected override bool Update()
{
(Entity as Line).EndPoint = mEndPoint;
return true;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nNext point:");
prOptions1.BasePoint = (Entity as Line).StartPoint;
prOptions1.UseBasePoint = true;
prOptions1.UserInputControls = UserInputControls.Accept3dCoordinates | UserInputControls.AnyBlankTerminatesInput
| UserInputControls.GovernedByOrthoMode | UserInputControls.GovernedByUCSDetect | UserInputControls.UseBasePointElevation
| UserInputControls.InitialBlankTerminatesInput | UserInputControls.NullResponseAccepted;
PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1);
if (prResult1.Status == PromptStatus.Cancel) return SamplerStatus.Cancel;
if (prResult1.Value.Equals(mEndPoint))
{
return SamplerStatus.NoChange;
}
else
{
mEndPoint = prResult1.Value;
return SamplerStatus.OK;
}
}
#endregion
#region Method to Call
public static bool Jig()
{
try
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
PromptPointResult ppr = ed.GetPoint("\nStart point");
if (ppr.Status != PromptStatus.OK) return false;
Point3d pt = ppr.Value;
Line ent = new Line(pt, pt);
ent.TransformBy(MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem);
LineJigger jigger = new LineJigger(ent);
PromptResult pr = ed.Drag(jigger);
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
{
ent.Dispose();
return false;
}
return true;
}
catch
{
return false;
}
}
public static bool Jig2()
{
try
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
PromptPointResult ppr = ed.GetPoint("\nStart point");
if (ppr.Status != PromptStatus.OK) return false;
Line ent = new Line(ppr.Value, ppr.Value);
ent.TransformBy(MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem);
LineJigger jigger = new LineJigger(ent);
PromptResult pr = ed.Drag(jigger);
if (pr.Status != PromptStatus.OK)
{
ent.Dispose();
return false;
}
else
{
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();
}
}
do
{
ent = new Line(ent.EndPoint, ent.EndPoint);
LineJigger jigger1 = new LineJigger(ent);
pr = ed.Drag(jigger1);
if (pr.Status != PromptStatus.OK)
{
ent.Dispose();
return pr.Status == PromptStatus.None || pr.Status == PromptStatus.Cancel;
}
else
{
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(jigger1.Entity);
tr.AddNewlyCreatedDBObject(jigger1.Entity, true);
tr.Commit();
}
}
} while (pr.Status != PromptStatus.None && pr.Status != PromptStatus.Cancel && pr.Status != PromptStatus.Error);
return pr.Status == PromptStatus.None || pr.Status == PromptStatus.Cancel;
}
catch
{
return false;
}
}
#endregion
}
}
As can be seen, the core jig code is exactly the same as we introduced about the single line jig. The only difference is that another method is added to jig the multi-line using the same jig core. A simple loop and a good logic have been applied here. Either the Return key or the Esc key or corresponding keywords from the context menu can finish the multi-line jig. If readers would like to distinguish the Esc behavior and the Return behavior, it surely can be easily done. Please go ahead if interested. Readers may also find a more concise way to do the loop, but I leave it as is for now.
As indicated by the various UserInputControls flags, the Line jig honors ortho mode and UCS and accepts any possible ways to finish the jig. A few highlights about the code may be more helpful:
• The UserInputControls enumerator values GovernedByUCSDetect and Accept3dCoordinates for the JigPromptPointOptions indicate if the point input honors the UCS and if the picked point is in 3D.
• An entity type needs to be specified in the EntityJig derivative, as Line here.
• The Sampler() override is to acquire input for the Line end point. The Line input point is input before jigging as it does not gain to put it in the jig process.
• 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.
• Please do not forget to handle the cancel/escape circumstance as demonstrated.
• The Update() override is to update the end point property of the Line.
• The Editor.Draw() is the power to fire the jig.
• Only after the jig succeeds should the Line be added to the database to avoid database messy.
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides a coder, Entity Jigger, to help us create entity jig code automatically, quickly and reliably.
Posted by: |