AutoCad 二次开发 jig操作之标注跟随线移动
在autocad当中,我认为的jig操作的意思就是即时绘图的意思,它能够实时的显示出当前的操作,以便我们直观的感受到当前的绘图操作是什么样子会有什么样的结果。比如我们自己写命令话一条直线,不用jig操作,只提示输入两个端点,我们在绘制过程中无法预先的感受到这条直线是在哪个位置,有多长,与x轴成什么角度,而是直接输入两点后就得到一条直线的结果了。还有当有了jig操作后,我们确定了一个端点后,在未输入第二个端点的时候,可以拖动鼠标拉长或缩短这条直线,也可以任意的绕第一个端点旋转这条直线。
我写了一个例子,是输入一条直线,并且在这条直线上建立一个对齐标注,拖动直线的同时,标注也跟随直线变化。我就以这个例子来具体的说说怎样实现一个jig操作。
首先要实现jig操作需要继承抽象类DrawJig, 它就是用来实现自定义的jig操作的,它的继承关系如图:
可以看到 DrawJig是继承自Jig的,有关jig的介绍:
- Gets a user drag movement
- Interprets this as a distance, angle, or point
- Uses this value to update the entity's data
- Calls the entity's WorldDraw method to redraw it on screen
这也是实现jig操作的步骤,大概意思就是用实时输入的距离、角度、点的数据去更新实体数据在屏幕上。要实现这个得在自定义的jig操作类中实现两个方法:
protected override SamplerStatus Sampler(JigPrompts prompts)
这个方法主要作用就是获取提供实时的数据输入的,这个JigPrompts和我们常见的那些输入数据的方法类似。这是它的继承结构:
Autodesk.AutoCAD.EditorInput.PromptOptions
Autodesk.AutoCAD.EditorInput.JigPromptOptions
Autodesk.AutoCAD.EditorInput.JigPromptGeometryOptions
Autodesk.AutoCAD.EditorInput.JigPromptAngleOptions
Autodesk.AutoCAD.EditorInput.JigPromptDistanceOptions
Autodesk.AutoCAD.EditorInput.JigPromptPointOptions
我们可以看到,我们能输入4种数据,这里我是选的JigPromptPointOptions,我们就用这里输入的数据来实时的更新直线的EndPoint,和对齐标注的xLine2Point。代码:
InputFunc = (prmpts) => { pointOpts.Message = msg; var res = prmpts.AcquirePoint(pointOpts); //Point就是我们要更新实体数据的点 if (res.Value == Point) { return SamplerStatus.NoChange; } else if (res.Value != Point) { Point = res.Value; return SamplerStatus.OK; } else { return SamplerStatus.Cancel; } };
protected override bool WorldDraw(WorldDraw draw)
这个方法就是把更新数据后的实体实时的绘制到屏幕上去。代码:
if (JigEnts.Count > 0) { //这是个委托,主要实现你要如何去更新你的实体 JigUpdateAction(this); foreach (var ent in JigEnts) { ent.WorldDraw(draw); } } return true;
JigUpdateAction代码:
(jig) => { line.EndPoint = jig.Point; dim.XLine2Point = jig.Point; dim.DimensionText = line.Length.ToString() ; var centerPt = new Point3d((line.StartPoint.X + jig.Point.X) / 2, (line.StartPoint.Y + jig.Point.Y) / 2, (line.StartPoint.Z + jig.Point.Z) / 2); dim.DimLinePoint = centerPt+ (jig.Point-line.StartPoint).GetNormal().RotateBy(Math.PI / 2, Vector3d.ZAxis) * 10; });
实现了以上两个方法基本上就可以了,最后你需要把实体加入到空间里面去。
完整代码:
using System; using System.Collections.Generic; using System.Linq; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.GraphicsInterface; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; namespace JigDimension { public class JigDim { [CommandMethod("myjig")] public void MyJigDimension() { var Doc = Application.DocumentManager.MdiActiveDocument; var Ed = Doc.Editor; var pointRes = Ed.GetPoint(new PromptPointOptions("请输入一地个点: ")); if (pointRes.Status != PromptStatus.OK) return; Line line = new Line() { StartPoint = pointRes.Value }; AlignedDimension dim = new AlignedDimension() { XLine1Point = line.StartPoint, DimensionStyle = ObjectId.Null }; JigPromptPointOptions jigOpts = new JigPromptPointOptions(); jigOpts.BasePoint = pointRes.Value; jigOpts.UseBasePoint = true; MyJig myJig = new MyJig(); myJig.PromptInput(jigOpts, "输入第二个点"); myJig.JigEnts.Add(line); myJig.JigEnts.Add(dim); myJig.SetJigUpdate((jig) => { line.EndPoint = jig.Point; dim.XLine2Point = jig.Point; dim.DimensionText = line.Length.ToString() ; var centerPt = new Point3d((line.StartPoint.X + jig.Point.X) / 2, (line.StartPoint.Y + jig.Point.Y) / 2, (line.StartPoint.Z + jig.Point.Z) / 2); dim.DimLinePoint = centerPt+ (jig.Point-line.StartPoint).GetNormal().RotateBy(Math.PI / 2, Vector3d.ZAxis) * 10; }); if (myJig.Drag() != PromptStatus.OK) { return; } myJig.JigEnts.ToSpace(); } } public class MyJig : DrawJig { public Point3d Point = Point3d.Origin; Func<JigPrompts, SamplerStatus> InputFunc; public List<Entity> JigEnts = new List<Entity>(); Action<MyJig> JigUpdateAction; public MyJig() { JigEnts.Clear(); InputFunc = null; } public void SetJigUpdate(Action<MyJig> action) { JigUpdateAction = action; } public void PromptInput(JigPromptPointOptions pointOpts,string msg) { InputFunc = (prmpts) => { pointOpts.Message = msg; var res = prmpts.AcquirePoint(pointOpts); //Point就是我们要更新实体数据的点 if (res.Value == Point) { return SamplerStatus.NoChange; } else if (res.Value != Point) { Point = res.Value; return SamplerStatus.OK; } else { return SamplerStatus.Cancel; } }; } protected override SamplerStatus Sampler(JigPrompts prompts) { if (InputFunc == null) { return SamplerStatus.NoChange; } return InputFunc.Invoke(prompts); } protected override bool WorldDraw(WorldDraw draw) { if (JigEnts.Count > 0) { //这是个委托,主要实现你要如何去更新你的实体 JigUpdateAction(this); foreach (var ent in JigEnts) { ent.WorldDraw(draw); } } return true; } public PromptStatus Drag() { return Application.DocumentManager.MdiActiveDocument.Editor .Drag(this).Status; } } }