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;
        }
    }

这个类在我的另一篇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());
        }

    }

原文地址:https://www.cnblogs.com/HelloQLQ/p/12148343.html

时间: 2024-10-12 01:25:23

AutoCad 二次开发 Jig操作之墙块的拖动的相关文章

AutoCAD二次开发&mdash;&mdash;AutoCAD.NET API开发环境搭建

AutoCAD二次开发--AutoCAD.NET API开发环境搭建 AutoCAD二次开发--AutoCAD.NET API开发环境搭建 AutoCAD二次开发工具:1986年AutoLisp,1989年ADS,1990年DCL,1993年ADS-RX,1995年ObjectARX,1996年Active X Automation(COM),1997年VBA,1998年Visual Lisp,2006年.net API(DLL). 趋势和方向:AutoCAD.net API(AutoCAD20

.NET AutoCAD二次开发之路(一、基础篇)

学习AutoCAD二次开发已经有一段时间了,磕磕碰碰,十分的艰辛枯燥.但回想一下还是会有些小激动,嘿嘿!最近这段时间一直都有这么个想法,就是将我学习CAD二次开发的过程用文字的方式记录下来,形成系列,并定期更新.主要内容就是记录自己每天学习过程中所碰见的问题和感悟,并总结今天所学到的内容.目的一是激励自己坚持下去,看着自己一步一步的提高,多有成就感.还有就是和大家积极沟通,希望能够指正我的错误,减少我的弯路.再者就是望能给后面学习的人一点点借鉴经验,好吧其实还有点装B的心里.废话不多说就进入今天

AutoCAD二次开发-使用ObjectARX向导创建应用程序(HelloWorld例子)

AutoCAD2007+vs2005 首先自己去网上搜索下载AutoCAD2007的ARX开发包. 解压后如下 打开后如下 classmap文件夹为C++类和.net类的框架图,是一个DWG文件. docs帮助文件 inc引用的头文件 lib引用的库文件 redistrib其他引用的库文件 samples例子 utils其他东西 打开utils 上面几个是头文件和库文件 ObjARXWiz这个文件夹是向导(2012以后的版本就没有了,要去官网单独下载,不和开发包在一起) 打开后如下 直接双击安装

1,下载和部署开发环境--AutoCAD二次开发(2020版)

教程说明: 本教程为2019年10月开始编撰,使用CAD官方最新版本的软件和库.对旧版本仍有参考价值. 本教程中使用的各种软件版本为官方指定匹配版本. 本教程需要你拥有编程基础,对于普通编程常识不再敷述.当然,你可以留言提问. 环境需求为: AutoCAD 2020版 ObjectARX SDK 下载地址:https://www.autodesk.com/developer-network/platform-technologies/autocad/objectarx-license-downl

.NET AutoCAD二次开发之路(一、直线篇)

我以前只有一点VB的基础,C语言也只是看过,学这个CAD二次开发,也是借工作之余研究下,我到现在已经从事机械行业5年了,中国的工业设计环境区别太大,各行各业的技术现状也不尽相同,但有一点是可以肯定的,那就是自动化,国外都在工业4.0了,我们还在互联网+,哎太out了,我也赶紧进修下,要不就淘汰了.所以我选择了CAD二次开发,主要还是跟专业接近,希望能越学越精吧,未来就让未来的我去面对! 今天主要总结下直线的创建,要想能在CAD中生成直线或者其他图形,都必须遵循几个步骤,那就是: 1.获取当前图形

AutoCAD二次开发

AutoCAD本身是功能强大.可配置性极高的软件,并且由于AutoCAD良好的软件架构,AutoCAD的二次开发能力也极强,几乎所有可见的软件功能都能在SDK内找到封装好的接口,由于AutoCAD SDK的向后兼容性极好,写出的程序几乎不用修改就可以适用于所有版本的AutoCAD. AutoCAD的第一代开发工具是AutoLISP,是AutoCAD定制的LISP语言,至今仍然是一个活跃的LISP分支,第二代开发工具是基于C语言的ADS,目前来看几乎被淘汰了,也是被AutoDesk公司标记为dep

承接 AutoCAD 二次开发 项目

本人有多年的CAD开发经验,独立完成多个CAD二次开发项目.熟悉.net及Asp.net开发技术,和Lisp开发技术. 现在成立了工作室,独立承接CAD二次开发项目.结项后提供源码及开发文档,有需要的话可以提供发票. 有需求的可以 [email protected] 联系开发事宜.

C# ObjectArx AutoCAD二次开发(转帖)

http://www.cnblogs.com/houlinbo/p/3325898.html 1.开发基本资料准备 用Vs2010进行Autocad 2010开发,首先下载ObjectArx 2010 SDK. http://download.autodesk.com/akdlm/esd/dlm/objectarx/ObjectARX_2010_Win_64_and_32Bit.exe 2.使用Visual Studio .NET来创建一个新的类库工程 (1)建立类库项目           启

AutoCad 二次开发 .net 之相同块的自动编号

主要步骤: 一.获取一个块的id: 其中oId就是了. 二.通过次oId获取块引用blkRef: 三.通过它获取所有相同的块引用的id集合: 四.通过步骤三的集合得到所有的块引用得到集合listBr: 五.遍历listBr,创建DBText编号 ,确定DBText在图中插入的位置,加入到集合listDBText: 在做第五步骤前,先要获取TextStyleId: 最后通过扩展方法加入到模型空间:listDBText.ToSpace(); ToSpace方法截图: 需要注意的地方:一定要是块定义,