AutoCAD .NET:使用 DrawJig 移动多个图元,任意数量/种类
AutoCAD .NET API 提供了两个具体的Jig类,供我们在不同情况下Jig不同的事物,即 EntityJig 和 DrawJig。EntityJig 用于Jig特定图元,顾名思义,DrawJig 用于夹具任何具有要绘制的图形,可以是单个图元、一组图元或 AutoCAD 中本机不可用的内容。
在这篇文章中,让我们看看如何使用 DrawJig 移动单个或多个实体,这些实体可以是任意数量的,并且可以在单个组中具有任何类型。
这是整个 DrawJig 实现类以及其中的测试命令。
#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 Autodesk.AutoCAD.GraphicsSystem;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.BoundaryRepresentation;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.ComponentModel;
using Autodesk.AutoCAD.Customization;
using Autodesk.AutoCAD.DataExtraction;
using Autodesk.AutoCAD.Diagnostics;
using Autodesk.AutoCAD.Internal;
using Autodesk.AutoCAD.LayerManager;
using Autodesk.AutoCAD.MacroRecorder;
using Autodesk.AutoCAD.Publishing;
using Autodesk.AutoCAD.PlottingServices;
using Autodesk.AutoCAD.Ribbon;
using MgdAcApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using MgdAcDocument = Autodesk.AutoCAD.ApplicationServices.Document;
using AcWindowsNS = Autodesk.AutoCAD.Windows;
#endregion
namespace AcadNetAddinWizard_Namespace
{
public class DrawJigger7 : DrawJig
{
#region Fields
private Point3d mBase;
private Point3d mLocation;
List<Entity> mEntities;
#endregion
#region Constructors
public DrawJigger7(Point3d basePt)
{
mBase = basePt.TransformBy(UCS);
mEntities = new List<Entity>();
}
#endregion
#region Properties
public Point3d Base
{
get { return mLocation; }
set { mLocation = value; }
}
public Point3d Location
{
get { return mLocation; }
set { mLocation = value; }
}
public Matrix3d UCS
{
get
{
return MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem;
}
}
#endregion
#region Methods
public void AddEntity(Entity ent)
{
mEntities.Add(ent);
}
public void TransformEntities()
{
Matrix3d mat = Matrix3d.Displacement(mBase.GetVectorTo(mLocation));
foreach (Entity ent in mEntities)
{
ent.TransformBy(mat);
}
}
#endregion
#region Overrides
protected override bool WorldDraw(Autodesk.AutoCAD.GraphicsInterface.WorldDraw draw)
{
Matrix3d mat = Matrix3d.Displacement(mBase.GetVectorTo(mLocation));
WorldGeometry geo = draw.Geometry;
if (geo != null)
{
geo.PushModelTransform(mat);
foreach (Entity ent in mEntities)
{
geo.Draw(ent);
}
geo.PopModelTransform();
}
return true;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nNew location:");
prOptions1.UseBasePoint = false;
PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1);
if (prResult1.Status == PromptStatus.Cancel || prResult1.Status == PromptStatus.Error)
return SamplerStatus.Cancel;
if (!mLocation.IsEqualTo(prResult1.Value, new Tolerance(10e-10, 10e-10)))
{
mLocation = prResult1.Value;
return SamplerStatus.OK;
}
else
return SamplerStatus.NoChange;
}
#endregion
#region Commands
public static DrawJigger7 jigger;
[CommandMethod("TestDrawJigger7")]
public static void TestDrawJigger7_Method()
{
try
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
PromptSelectionResult selRes = ed.GetSelection();
if (selRes.Status != PromptStatus.OK) return;
PromptPointOptions prOpt = new PromptPointOptions("\nBase point:");
PromptPointResult pr = ed.GetPoint(prOpt);
if (pr.Status != PromptStatus.OK) return;
jigger = new DrawJigger7(pr.Value);
using (Transaction tr = db.TransactionManager.StartTransaction())
{
foreach (ObjectId id in selRes.Value.GetObjectIds())
{
Entity ent = (Entity)tr.GetObject(id, OpenMode.ForWrite);
jigger.AddEntity(ent);
}
PromptResult jigRes = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.Drag(jigger);
if (jigRes.Status == PromptStatus.OK)
{
jigger.TransformEntities();
tr.Commit();
}
else
tr.Abort();
}
}
catch (System.Exception ex)
{
MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.ToString());
}
}
#endregion
}
}
加载测试部件并运行测试命令后,我们将看到此处的Jigger的行为与本机 AutoCAD MOVE 命令几乎完全相同。
因此,使用如此简洁的代码,可以进一步压缩,例如删除那些未使用的命名空间,我们已经重现了看起来相当复杂的AutoCAD MOVE命令的确切行为。
有关代码的一些要点可能更有帮助。
• DrawJig 的关键是它的 WorldDraw()方法。它提供了绘制任何图形的功能。
• WorldGeometry 实例提供了各种方法来绘制我们想要的任何内容。
• 它还为我们提供了一种结构化的简单方法来处理任何矩阵变换,就像我们在这里对位移矩阵所做的那样。
• Sampler()是另一种核心方法,用于收集用户输入,例如大小写中的光标位置。
• 虽然Sampler()看起来与 EntityJig 中的完全相同,但它有根本的区别。在EntityJig中,除非使用输入控件明确指定,否则收集的点位于UCS中;但在 DrawJig 中,点坐标位于 WCS 中。
• 但是Editor.GetPoint()方法返回 UCS 中的基点。这就解释了为什么我们必须将基点转换为 WCS 以使事情保持一致。
• WorldGeometry 可以绘制从 Drawable 接口派生的任何内容,然后绘制 Entity 类,因此我们可以在新位置重新绘制实体。
• PushModelTransform 和 PopModelTransform 机制让我们的生活更轻松。我们不必像之前在 EntityJig 中那样将处理的新位置缓存为新基点来移动单个实体。
• 通常,我们不会将实体指针传递给 DrawJig,因为它不仅应该关心特定实体的图形,而且在这里,我们将实体指针列表传递到 DrawJig 中,以便同时更新它们的图形。
• WorldGeometry.Draw 非常友好,我们可以用它来逐个绘制关注的实体。