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("請輸入一地個點:\n")); 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; } } }