zoukankan      html  css  js  c++  java
  • 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("请输入一地个点:
    "));
    
                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
  • 相关阅读:
    硬盘安装CentOS 6.0(超级详细图文教程)
    js获取当前URL、域名、端口号
    前端匹配表情
    记一次复杂的数据转换
    浅拷贝与深拷贝
    js统计数组中元素的重复次数(二)
    js计算数组中某个元素重复出现的个数(一)
    移动端——处理rem根字体
    js实现简单的双向绑定
    JS正则截取两个字符串之间的字符串
  • 原文地址:https://www.cnblogs.com/HelloQLQ/p/12148343.html
Copyright © 2011-2022 走看看