測試結果:
主要思路:選擇一段多段線,使用封裝的jig類進行實時拖動,其原理就是在拖動的時候,確定被拖動的邊,我是選擇離輸入第一個點最近的邊作為拖動邊,有了這條邊,就能確定需要實時更改的點了,然后當鼠標拖動的時候,限制拖動方向只能是X軸或者Y軸變換,詳細我在代碼里都寫了注釋的。不足之處就是選擇之后,我是把原來的對象復制一份,在刪除了原對象,不知道是不是這個原因,Polyline會在選擇之后消失,再次點擊又出現了。我試了如果直接以寫的方式操作原對像,cad會報錯,說NotOpenForWrite,我也不知道這是什么原因。下面貼出所有的代碼。
Jig操作類:

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; } }
這個類在我的另一篇jig操作里做了點介紹的:
https://www.cnblogs.com/HelloQLQ/p/12000879.html
命令類:

public class MyDrag { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; Database db = Application.DocumentManager.MdiActiveDocument.Database; Polyline pl = null; bool IsDrag = false; [CommandMethod("MyDrag")] public void DragIt() { IsDrag = false; PromptEntityOptions entOpts = new PromptEntityOptions("請選擇Polyline"); entOpts.SetRejectMessage("請選擇多段線"); entOpts.AddAllowedClass(typeof(Polyline), true); var pEntRes = ed.GetEntity(entOpts); if (pEntRes.Status != PromptStatus.OK) return; Polyline plCo = null; using (var trans = db.TransactionManager.StartTransaction()) { pl = trans.GetObject(pEntRes.ObjectId, OpenMode.ForWrite) as Polyline; //這里如果不復制,直接操作pl,雖然是以寫的方式打開的實體,但是會報錯說NotOpenForWrite plCo = pl.Clone() as Polyline; pl.Erase(); trans.Commit(); } List<LineSegment2d> listL2d = new List<LineSegment2d>(); for (int i = 0; i < pl.NumberOfVertices - 1; i++) { listL2d.Add(pl.GetLineSegment2dAt(i)); } var pointRes = ed.GetPoint(new PromptPointOptions("請輸入一地個點:\n")); if (pointRes.Status != PromptStatus.OK) return; Vector2d v2d = new Vector2d(0, 0); JigPromptPointOptions jigOpts = new JigPromptPointOptions(); MyJig myJig = new MyJig(); myJig.PromptInput(jigOpts, "拖動鼠標"); myJig.JigEnts.Add(plCo); int dir = -1; myJig.SetJigUpdate((jig) => { if (jig.JigEnts == null || jig.JigEnts.Count == 0) { return; } Polyline p = jig.JigEnts[0] as Polyline; var pt1 = pointRes.Value; var pt2 = jig.Point; var vec = pt2 - pt1; /*獲取鼠標拖動方向,主要思路 *當拖動的距離拖動前按下的那個點的 * 距離>1的時候,計算是X軸方向還是Y軸方向 * 因為第一次判斷,如果距離過下方向不准確。 * 並且這個方向一確定,就不在更改。 */ if (!IsDrag) { if (vec.Length > 1) { IsDrag = true; if (Math.Abs(vec.X) > Math.Abs(vec.Y)) { dir = 0; } else { dir = 1; } } } //向右或者向左 if (dir == 0) { v2d = new Vector2d(vec.X, 0); } else//向上或者向下 { v2d = new Vector2d(0, vec.Y); } /* * 確定要拖動的邊是選擇距離鼠標按下的那個點最近的邊 */ double minLength = double.MaxValue; int index = -1; foreach (var i in Enumerable.Range(0, listL2d.Count)) { var l = listL2d[i]; double dis = l.GetDistanceTo(new Point2d(pointRes.Value.X, pointRes.Value.Y)); if (dis < minLength) { minLength = dis; index = i; } } var l2d = listL2d[index]; Matrix2d mtx2d = Matrix2d.Displacement(v2d); var ptGet1 = l2d.StartPoint; var ptGet2 = l2d.EndPoint; //實時得到變化的點 var ptStart = ptGet1.TransformBy(mtx2d); var ptEnd = ptGet2.TransformBy(mtx2d); var vecGet = ptGet2 - ptGet1; //判斷鼠標移動的方向和被拖動的邊是否是在大致的同一方向 //如果不是,就允許拖動 if (dir == 0 && (Math.Abs(vecGet.X) < Math.Abs(vecGet.Y)) || dir == 1 && (Math.Abs(vecGet.X) > Math.Abs(vecGet.Y))) { p.SetPointAt(index, ptStart); p.SetPointAt(index + 1, ptEnd); //如果polyline是封閉的,要判斷被拖動的點是否是閉合位置上的點, //如果是,要一致更改起點和封閉點 if (p.Closed) { if (index == 0) { p.SetPointAt(p.NumberOfVertices - 1, ptStart); } if (index + 1 == 0) { p.SetPointAt(p.NumberOfVertices - 1, ptEnd); } if (index == p.NumberOfVertices - 1) { p.SetPointAt(0, ptStart); } if (index + 1 == p.NumberOfVertices - 1) { p.SetPointAt(0, ptEnd); } } } }); if (myJig.Drag() != PromptStatus.OK) { return; } IsDrag = false; //加入到模型空間 myJig.JigEnts.ToSpace(); myJig.JigEnts.ForEach(a => a.Dispose()); } }