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 even something that is not available natively in AutoCAD.
We have demonstrated various ways to jig a block (INSERT as used in AutoCAD users and BlockReference in programmers) such as by its position, rotation, both of these factors, or even from the block name input on, with the original graphics highlighted, keyword input or user cancellation handling.
However, if they are tried in a UCS which is not exactly the same as the WCS, those jigs may not behave as expected. Do not worry. We will be addressing this issue in this post.
Here is the test command for the block insertion jig which honors AutoCAD UCS:
[CommandMethod("TestEntityJigger7")]
public static void TestEntityJigger7_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
PromptResult pr = ed.GetString("\nBlock name:");
if (pr.Status == PromptStatus.OK)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[pr.StringResult], OpenMode.ForRead) as BlockTableRecord;
if (btr != null)
{
BlockReference ent = new BlockReference(new Point3d(0, 0, 0), btr.ObjectId);
if (BlockMovingRotating.Jig(ent))
{
BlockTableRecord modelspace = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
modelspace.AppendEntity(ent);
tr.AddNewlyCreatedDBObject(ent, true);
tr.Commit();
}
else
{
tr.Abort();
}
}
}
}
}
Here is how the block jig behaves in AutoCAD in a UCS after the test command runs, a valid block name is input, the block position is pointed, and the block rotation angle is jigging:
As can be seen, the block (containing a rectangle) appears just good in the UCS and the block jig honors the UCS all well not only for the position input but also for the rotation angle. If it is tried in the WCS, it will behave well 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 BlockMovingRotating : EntityJig
{
#region Fields
public int mCurJigFactorNumber = 1;
private Point3d mPosition; // Factor #1
private double mRotation; // Factor #2
private double mAngleOffset;
#endregion
#region Constructors
public BlockMovingRotating(Entity ent)
: base(ent)
{
ent.TransformBy(MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem);
mAngleOffset = (ent as BlockReference).Rotation;
}
#endregion
#region Overrides
protected override bool Update()
{
switch (mCurJigFactorNumber)
{
case 1:
(Entity as BlockReference).Position = mPosition;
break;
case 2:
(Entity as BlockReference).Rotation = mAngleOffset + mRotation;
break;
default:
return false;
}
return true;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
switch (mCurJigFactorNumber)
{
case 1:
JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nBlock position:");
prOptions1.UserInputControls = UserInputControls.GovernedByUCSDetect | UserInputControls.UseBasePointElevation | UserInputControls.Accept3dCoordinates;
PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1);
if (prResult1.Status == PromptStatus.Cancel) return SamplerStatus.Cancel;
if (prResult1.Value.Equals(mPosition))
{
return SamplerStatus.NoChange;
}
else
{
mPosition = prResult1.Value;
return SamplerStatus.OK;
}
case 2:
JigPromptAngleOptions prOptions2 = new JigPromptAngleOptions("\nBlock rotation angle:");
prOptions2.BasePoint = mPosition;
prOptions2.UseBasePoint = true;
PromptDoubleResult prResult2 = prompts.AcquireAngle(prOptions2);
if (prResult2.Status == PromptStatus.Cancel) return SamplerStatus.Cancel;
if (prResult2.Value.Equals(mRotation))
{
return SamplerStatus.NoChange;
}
else
{
mRotation = prResult2.Value;
return SamplerStatus.OK;
}
default:
break;
}
return SamplerStatus.OK;
}
#endregion
#region Method to Call
public static bool Jig(BlockReference ent)
{
try
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
BlockMovingRotating jigger = new BlockMovingRotating(ent);
PromptResult pr;
do
{
pr = ed.Drag(jigger);
} while (pr.Status != PromptStatus.Cancel &&
pr.Status != PromptStatus.Error &&
pr.Status != PromptStatus.Keyword &&
jigger.mCurJigFactorNumber++ <= 2);
return pr.Status == PromptStatus.OK;
}
catch
{
return false;
}
}
#endregion
}
}
As can be noticed, the extra considerations are the UserInputControls enumerator values (UserInputControls.GovernedByUCSDetect | UserInputControls.UseBasePointElevation | UserInputControls.Accept3dCoordinates) for the JigPromptPointOptions and the UCS transformation which matrix can be obtained from the static property Editor.CurrentUserCoordinateSystem.
Some other highlights about the code may be helpful as well as usual:
• An entity type needs to be specified in the EntityJig derivative, as BlockReference here.
• The Sampler() override is to acquire input for the block position and rotation angle 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.
• Please do not forget to handle the cancel/escape circumstance as demonstrated.
• The Update() override is to update the position and the rotation properties of the block 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 needs to think about the PromptStatus.Keyword case of the PromptResult after each Jig Drag.
• Only after the jig succeeds should the BlockReference be added to the database to avoid database corruption.
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