测试结果:

主要思路:选择一段多段线,使用封装的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 > )
{
//这是个委托,主要实现你要如何去更新你的实体
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 = ; i < pl.NumberOfVertices - ; i++)
{
listL2d.Add(pl.GetLineSegment2dAt(i));
} var pointRes = ed.GetPoint(new PromptPointOptions("请输入一地个点:\n")); if (pointRes.Status != PromptStatus.OK) return; Vector2d v2d = new Vector2d(, ); JigPromptPointOptions jigOpts = new JigPromptPointOptions(); MyJig myJig = new MyJig(); myJig.PromptInput(jigOpts, "拖动鼠标");
myJig.JigEnts.Add(plCo); int dir = -; myJig.SetJigUpdate((jig) =>
{
if (jig.JigEnts == null || jig.JigEnts.Count == )
{
return;
} Polyline p = jig.JigEnts[] as Polyline; var pt1 = pointRes.Value; var pt2 = jig.Point; var vec = pt2 - pt1; /*获取鼠标拖动方向,主要思路
*当拖动的距离拖动前按下的那个点的
* 距离>1的时候,计算是X轴方向还是Y轴方向
* 因为第一次判断,如果距离过下方向不准确。
* 并且这个方向一确定,就不在更改。
*/
if (!IsDrag)
{
if (vec.Length > )
{
IsDrag = true; if (Math.Abs(vec.X) > Math.Abs(vec.Y))
{
dir = ; }
else
{
dir = ;
}
} }
//向右或者向左
if (dir == )
{ v2d = new Vector2d(vec.X, ); }
else//向上或者向下
{
v2d = new Vector2d(, vec.Y); } /*
* 确定要拖动的边是选择距离鼠标按下的那个点最近的边
*/
double minLength = double.MaxValue; int index = -; foreach (var i in Enumerable.Range(, 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 == && (Math.Abs(vecGet.X) < Math.Abs(vecGet.Y)) ||
dir == && (Math.Abs(vecGet.X) > Math.Abs(vecGet.Y)))
{
p.SetPointAt(index, ptStart);
p.SetPointAt(index + , ptEnd); //如果polyline是封闭的,要判断被拖动的点是否是闭合位置上的点,
//如果是,要一致更改起点和封闭点
if (p.Closed)
{
if (index == )
{
p.SetPointAt(p.NumberOfVertices - , ptStart);
}
if (index + == )
{
p.SetPointAt(p.NumberOfVertices - , ptEnd);
}
if (index == p.NumberOfVertices - )
{
p.SetPointAt(, ptStart);
}
if (index + == p.NumberOfVertices - )
{
p.SetPointAt(, ptEnd);
}
}
}
}); if (myJig.Drag() != PromptStatus.OK)
{ return;
} IsDrag = false; //加入到模型空间
myJig.JigEnts.ToSpace();
myJig.JigEnts.ForEach(a => a.Dispose());
} }

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

  1. AutoCad 二次开发 jig操作之标注跟随线移动

    AutoCad 二次开发 jig操作之标注跟随线移动 在autocad当中,我认为的jig操作的意思就是即时绘图的意思,它能够实时的显示出当前的操作,以便我们直观的感受到当前的绘图操作是什么样子会有什 ...

  2. AutoCad 二次开发 文字镜像

    AutoCad 二次开发 文字镜像 参考:https://adndevblog.typepad.com/autocad/2013/10/mirroring-a-dbtext-entity.html 在 ...

  3. AutoCAD二次开发——AutoCAD.NET API开发环境搭建

    AutoCAD二次开发工具:1986年AutoLisp,1989年ADS,1990年DCL,1993年ADS-RX,1995年ObjectARX,1996年Active X Automation(CO ...

  4. AutoCad 二次开发 .net 之层表的增加 删除 修改图层颜色 遍历 设置当前层

    AutoCad 二次开发 .net 之层表的增加 删除 修改图层颜色 遍历 设置当前层 AutoCad 二次开发 .net 之层表的增加 删除 修改图层颜色 遍历 设置当前层我理解的图层的作用大概是把 ...

  5. 1,下载和部署开发环境--AutoCAD二次开发

    环境需求为: AutoCAD 2020版 ObjectARX SDK 下载地址:https://www.autodesk.com/developer-network/platform-technolo ...

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

    AutoCAD2007+vs2005 首先自己去网上搜索下载AutoCAD2007的ARX开发包. 解压后如下 打开后如下 classmap文件夹为C++类和.net类的框架图,是一个DWG文件. d ...

  7. 我的AutoCAD二次开发之路 (一)

    原帖地址 http://379910987.blog.163.com/blog/static/33523797201011184552167/ 今天在改代码的时候,遇到了AddVertexAt方法的用 ...

  8. Autocad中使用命令来调用python对Autocad二次开发打包后的exe程序

    在Autocad中直接调用Python二次开发程序是有必要的,下面介绍一种方法来实现这个功能: 其基本思路是:先将二次开发的程序打包为可执行程序exe,然后编写lsp文件,该文件写入调用exe程序的语 ...

  9. 承接 AutoCAD 二次开发 项目

    本人有多年的CAD开发经验,独立完成多个CAD二次开发项目.熟悉.net及Asp.net开发技术,和Lisp开发技术. 现在成立了工作室,独立承接CAD二次开发项目.结项后提供源码及开发文档,有需要的 ...

随机推荐

  1. Core Data 数据出现Fault

    I am mapping Json Data from Server using Restkit and I am Displaying those data by fetching from db. ...

  2. oracle 识别’低效执行’的SQL语句

    用下列SQL工具找出低效SQL: SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUFFER_ ...

  3. oracle 用EXISTS替代IN

    在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率. 低效: SELECT * FROM EMP ( ...

  4. Codeforces Round #172 (Div. 1 + Div. 2)

    A. Word Capitalization 模拟. B. Nearest Fraction 枚举. C. Rectangle Puzzle 求出两个矩形的点,套简单多边形的面积交板子. D. Max ...

  5. 在linux上安装pear

    在搭建centreon的过程中,需要pear模块支持. 什么是pear pear是PHP扩展与应用库(the PHP Extension and Application Repository)的缩写. ...

  6. vscode编辑如何保存时自动校准eslint规范

    在日常开发中,一个大点的项目会有多人参与,那么可能就会出现大家的代码风格不一,各显神通,这个时候就要祭出我们的eslint. 在这之前磨刀不误砍柴工,我们先来配置一下我们的代码编辑工具,如何在vsco ...

  7. [转载]Eclipse luna tomcat 控制台 中文乱码

    http://hahalzb.iteye.com/blog/709109 今天做S2SH集成的例子,所有该设置的地方都设置成了UTF-8,包括tomcat的配置文件server.xml.web.xml ...

  8. Java中的元注解

    注解为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据. 通过使用注解,我们可以将这些元数据保存在Java源代码中,并利用annotation API为自己的 ...

  9. H3C 基于ACL的包过滤技术

  10. Laravel5 call to undefined function openssl cipher iv length() 报错 PHP7开启OpenSSL扩展失败

    在安装laravel5.5后, 访问显示报错. call to undefined function openssl cipher iv length() 经查为php7.1的OpenSSL扩展加载失 ...