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.
In this article, let us see how to move and rotate a Block (a commonly used but confusing term)/BlockReference (API term) /INSERT (AutoCAD term) using EntityJig.
Here is the test command for the block moving and rotating jig we are going to talk about:
[CommandMethod("TestEntityJigger6")]
public static void TestEntityJigger6_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
PromptEntityResult selRes = ed.GetEntity("Pick a block:");
if (selRes.Status == PromptStatus.OK)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockReference ent = tr.GetObject(selRes.ObjectId, OpenMode.ForWrite) as BlockReference;
if (ent != null)
{
using (Transaction tr1 = db.TransactionManager.StartTransaction())
{
ent.Highlight();
tr1.Commit();
}
if (BlockMovingRotating.Jig(ent))
tr.Commit();
else
tr.Abort();
}
}
}
}
Here is how the block moving and rotating jig behaves in AutoCAD after the test command runs and a block is picked:
As can be seen, the block moving and rotating behavior looks very natural, almost the same as the AutoCAD move and rotate command exhibits. This is achieved easily and reliably by applying a sub transaction as demonstrated in the succinct test command. And better, a few other situations have been nicely handled as well. The block’s graphics is only highlighted temporarily during the jigging period. In case of anything wrong during the moving or rotating or users just cancel or escape out the operation, the block will be restored to its very original status automatically thus nothing messy about the database.
So this is a simple but very useful practical example that demonstrates the usage of the AutoCAD .NET sub transaction. It is not something fancy that just makes people wonder.
Here is the core source about the block moving and rotating jig class derived from the EntityJig:
#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
#endregion
#region Constructors
public BlockMovingRotating(Entity ent)
: base(ent)
{
}
#endregion
#region Overrides
protected override bool Update()
{
switch (mCurJigFactorNumber)
{
case 1:
(Entity as BlockReference).Position = mPosition;
break;
case 2:
(Entity as BlockReference).Rotation = mRotation;
break;
default:
return false;
}
return true;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
switch (mCurJigFactorNumber)
{
case 1:
JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nBlock position:");
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 = (Entity as BlockReference).Position;
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
}
}
A few highlights about the code may be helpful:
• An entity type needs to be specified in the EntityJig derivative, as BlockReference here.
• The Sampler() override is to acquire input for the new position and rotation angle.
• 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 both the block position and the block rotation properties as acquired in the Sampler().
• The Editor.Draw() is the power to fire the jig.
• The last but important, please return a good status value to the caller so that it knows whether to really modify the block or roll any changes back.
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides a coder, Entity Jigger, to help us create entity jig code automatically, quickly and reliably.
Hi spider,
is it possible to auto align jig to object like alignment in dynamic block
only I want it in 3D
Also is it possible to rotate the jig entity using mouse scroll? lets say 1 scroll is 90°
Sorry I'm absolute beginner here
Posted by: Indrawan Adi wicaksono | 04/15/2012 at 10:36 AM
They seem all possible to me. If a bit more details could be provided, some posts may be addressing these cases in the future.
For example, how would you like a line or circle jig to auto aligh in a dynamic block?
Posted by: Spiderinnet1 | 04/15/2012 at 06:45 PM
The recent post addresses your second query:
AutoCAD .NET: EntityJig – Mouse Wheel Up/Down as Rotation Increment/Decrement During Block/Insert Rotating
http://spiderinnet1.typepad.com/blog/2012/04/autocad-net-entityjig-mouse-wheel-updown-as-rotation-incrementdecrement-during-blockinsert-rotating.html
Posted by: Spiderinnet1 | 04/17/2012 at 04:09 AM
Hi Spider...
Thanks a lot for this code. Its really a very good help.
I'm actually working with multiple *.dwg files and I used this code to get the block from dwg files, let the user move in drawing area and when he/she drops, let the user rotate it.
Best regards
Farrukh
Posted by: Account Deleted | 07/03/2012 at 04:18 AM
Although, I'm going to modify it so that user can Resize it after user would drop/place it. If you could suggest something, I would really appreciate that...
Best regards
Farrukh
Posted by: Account Deleted | 07/03/2012 at 04:20 AM
Farrukh,
Glad to hear you found it useful.
In terms of 'Resize', if you mean Scale, there are quite some other articles on this blog to address the Jig and Scale. Here are a few of them:
AutoCAD .NET: EntityJig – Insert and Non-Uniform Scale Block (INSERT/BlockReference)
http://spiderinnet1.typepad.com/blog/2012/02/autocad-net-entityjig-insert-and-non-uniform-scale-block-insertblockreference.html
AutoCAD .NET: EntityJig – Dynamic Scale and Jig
http://spiderinnet1.typepad.com/blog/2012/06/autocad-net-entityjig-dynamic-scale-and-jig.html
AutoCAD .NET: Use DrawJig to Dynamically Move Rotate and Scale Multiple Entities of Any Kinds
http://spiderinnet1.typepad.com/blog/2012/06/autocad-net-use-drawjig-to-dynamically-move-rotate-and-scale-multiple-entities-of-any-kinds.html
AutoCAD .NET: Use DrawJig To Scale Single or Multiple Entities of Any Kinds
http://spiderinnet1.typepad.com/blog/2012/05/autocad-net-use-drawjig-to-scale-single-or-multiple-entities-of-any-kinds.html
Posted by: Spiderinnet1 | 07/03/2012 at 05:42 PM
Hello Spider,
I have custom block (simple rectangle) that has linear parameter, associated with stretch actions to stretch both opposite sides. Do you think the block can be inserted with its length set to 0, and when the block is rotated at the same time its stretched.
Thank you.
Posted by: Damyan | 06/08/2014 at 07:02 PM
Hi Damyan, it seems your task has nothing to do with EntityJig or DrawJig, or even AutoCAD .Net programming related. Instead, it's dynamic block related. In terms of dynamic block parameters and actions, somewhere else might have better information.
Posted by: Spiderinnet1 | 06/09/2014 at 02:00 AM
Thank you for your prompt response.
I wanted to reused/modify the code provided in the example above and add to the jig the possibility to stretch the block while at the same time I rotate it.
Posted by: Damyan | 06/09/2014 at 09:55 AM
Damyan, you are welcome. If you meant scale by 'stretch', a few other posts on the blog address it.
AutoCAD .NET: EntityJig – Insert and Non-Uniform Scale Block (INSERT/BlockReference)
http://spiderinnet1.typepad.com/blog/2012/02/autocad-net-entityjig-insert-and-non-uniform-scale-block-insertblockreference.html
AutoCAD .NET: EntityJig – Insert and Uniform Scale Block (INSERT/BlockReference)
http://spiderinnet1.typepad.com/blog/2012/02/autocad-net-entityjig-insert-and-uniform-scale-block-insertblockreference.html
AutoCAD .NET: EntityJig – Dynamic Scale and Jig
http://spiderinnet1.typepad.com/blog/2012/06/autocad-net-entityjig-dynamic-scale-and-jig.html
Posted by: Spiderinnet1 | 06/09/2014 at 03:33 PM
Damyan, a new jig was created to address this scenario.
AutoCAD .NET: EntityJig – Move & Stretch Block (BlockReference/INSERT) With Single Drag
http://spiderinnet1.typepad.com/blog/2014/06/autocad-net-entityjig-move-stretch-block-blockreferenceinsert-with-single-drag.html
We believe it meets your need.
Posted by: Spiderinnet1 | 06/09/2014 at 09:01 PM
Thank you very much for the wonderful coding. Seeing the elegant and simple way of you explained jigging prompt me to try it. I will try to adapt your code to my needs as much as I can.
Obviously (because of the many different names used for identical items) I am not able to explain linear parameter so I use AutoCad explanation.
http://docs.autodesk.com/ACD/2010/ENU/AutoCAD%202010%20User%20Documentation/index.html?url=WS1a9193826455f5ff211a40be11dcc57291c1d63.htm,topicNumber=d0e73591.
Its like nonuniform scaling but its not. Its part of dynamic blocks and can be associated with stretching action in my case.
Thank you for all your help.
Posted by: Damyan | 06/10/2014 at 10:53 AM
Damyan, you are welcome.
Posted by: Spiderinnet1 | 06/10/2014 at 01:14 PM