AutoCad 二次開發 Jig操作之牆塊的拖動


測試結果:

 主要思路:選擇一段多段線,使用封裝的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;
        }
    }
View Code

這個類在我的另一篇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());
        }

    }
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM