AutoCad 二次开发 文字镜像

在autocad中如果使用Mirror命令把块参照给镜像了(最终得到一个对称的块),块里面的文字包括DBText和MText以及标注上面的文字都会被对称,变得不易阅读。而在单个字体实体和标注实体镜像的时候只要设置系统变量mirrtext为0镜像后的文字就不会与原文字对称变成我们未学习过的文字了。
 
所以我们在镜像块的时候就可以先把块炸开是用快捷键X,或者输入explode,然后在使用镜像命令。之后在把对称后的实体集合组成一个新的块。不过这样操作十分的繁琐,我觉得其中这样做的优势是mirror时的jig操作可以很方便的预先知道我们想要的对称后的结果。但如果用代码实现这种jig操作,我觉得有点复杂,目前我还不知道怎么实现。
 
我要讲的主要就是用代码来实现块的镜像。难点就在与文字的镜像,和标注的镜像。这篇文章先讲文字的镜像。文字镜像的主要步骤分为:
1.找到镜像前文字边界的四个角,这四个角构成了一个矩形,我们要求得这个矩形的长和宽所代表的向量。
2.判断文字镜像后的方向,如果是偏向朝Y轴镜像,那么文字镜像后的方向是沿着X轴翻转的,如果是偏向朝X轴镜像,那么文字镜像后的方向是沿着X轴翻转的。这里我以沿着Y轴镜像为例子。
3.移动镜像后切被翻转后的文字,这里也是根据镜像轴的不同,需按不同的向量来移动。
 
详细情况见图:
图中左边是要镜像的文字,文字上的蓝色线,和黄色线是我调试的时候加入的,黄线左端是 pt1,右端是pt2,蓝线左端是pt3,右端是pt4。 中间的竖线是Y轴镜像线,右边就是不同情况下镜像后的文字。其中黄色部分表示正确的镜像结果,红色部分表示:镜像后延第一个步骤移动后求得的向量移动了文字的position但是没翻转的结果。黑色部分表示:镜像后翻转了文字但文字的position没有按向量移动的结果。
下面我就来仔细分析一下代码:
要实现第一步骤,前提是要有一段P/Invoke的代码:
其中 引入的acdb22.dll是 autocad2018中的版本,不同版本,这个dll后面的数字不一样。我们可以到cad安装目录下查找acdb几个字,找到后面带数字的就是了,64位的安装目录默认位置:C:\Program Files\Autodesk\AutoCAD 2018。这两个函数一个是32位,一个是64位,具体用哪个后面的代码会自动判断。这个函数作用我觉得主要是求 这个name。
 
这里用到了accore.dll,有的cad版本没有这个dll,就用acad.exe代替就可以了。上面的acdbEntGet主要是根据entity的名字求的entity实体的Intptr,下面的函数时求的文字边界对角点,这里注意,我把这个两个点用直线打印在cad空间里,发现它时在原点,没旋转的线,但其实文字不的position不在原点,也带有旋转角度。后面要求的文字边界向量就是根据这两个点来的。
上面求得的pt1,pt2 经过:
pt1 = pt1.TransformBy(rotMat).Add(dbText.Position.GetAsVector());
pt2 = pt2.TransformBy(rotMat).Add(dbText.Position.GetAsVector());
这种操作就得到了第一幅图中的黄线。
在经过这样的操作,得到的pt3 和pt4就是第一幅图的蓝线。这其中的rotDir和linDir就是我们要求得的宽和长代表的向量了,然后在把它给镜像了得到的mirRotDir和mirLinDir就是镜像后的文字要移动的向量了,这里第一步就结束了。
第二步,第三步:

大的话,就说明文字需要朝X轴翻转,所以这里的IsMirroredInX=true就代表需要朝X轴翻转。
紧接着下面句,如果没加mirLineDir这个向量,就会出现第一幅图中的画黑线的情况,如果不加IsMirrorInX就会出现画红线的情况。
到这里就全部结束了。
下面给出所有代码:
  1. public class MyMirror
  2. {
  3. Document Doc = Application.DocumentManager.MdiActiveDocument;
  4. Editor Ed = Application.DocumentManager.MdiActiveDocument.Editor;
  5. Database Db = Application.DocumentManager.MdiActiveDocument.Database;
  6.  
  7. List<Entity> list = new List<Entity>();
  8. List<ObjectId> listOId = new List<ObjectId>();
  9.  
  10. [CommandMethod("testM")]
  11.  
  12. public void MirrorTextCmd()
  13.  
  14. {
  15.  
  16. Document doc = Application.DocumentManager.MdiActiveDocument;
  17.  
  18. Database db = doc.Database;
  19.  
  20. Editor ed = doc.Editor;
  21.  
  22. //Entity selection
  23.  
  24. PromptEntityOptions peo = new PromptEntityOptions(
  25.  
  26. "\nSelect a text entity:");
  27.  
  28. peo.SetRejectMessage("\nMust be text entity...");
  29.  
  30. peo.AddAllowedClass(typeof(DBText), true);
  31.  
  32. PromptEntityResult perText = ed.GetEntity(peo);
  33.  
  34. if (perText.Status != PromptStatus.OK)
  35.  
  36. return;
  37.  
  38. peo = new PromptEntityOptions("\nSelect a mirror line:");
  39.  
  40. peo.SetRejectMessage("\nMust be a line entity...");
  41.  
  42. peo.AddAllowedClass(typeof(Line), true);
  43.  
  44. PromptEntityResult perLine = ed.GetEntity(peo);
  45.  
  46. if (perLine.Status != PromptStatus.OK)
  47.  
  48. return;
  49.  
  50. using (Transaction tr = db.TransactionManager.StartTransaction())
  51.  
  52. {
  53.  
  54. Line line = tr.GetObject(perLine.ObjectId, OpenMode.ForRead)
  55.  
  56. as Line;
  57.  
  58. Line3d mirrorLine = new Line3d(
  59.  
  60. line.StartPoint,
  61.  
  62. line.EndPoint);
  63.  
  64. MirrorText(perText.ObjectId, mirrorLine);
  65.  
  66. tr.Commit();
  67.  
  68. }
  69.  
  70. }
  71.  
  72. void MirrorText(ObjectId oId, Line3d mirrorLine)
  73.  
  74. {
  75.  
  76. Database db = oId.Database;
  77.  
  78. using (Transaction tr = db.TransactionManager.StartTransaction())
  79.  
  80. {
  81.  
  82. // Get text entity
  83.  
  84. DBText dbText = tr.GetObject(oId, OpenMode.ForRead)
  85.  
  86. as DBText;
  87.  
  88. // Clone original entity
  89.  
  90. DBText mirroredTxt = dbText.Clone() as DBText;
  91.  
  92. // Create a mirror matrix
  93.  
  94. Matrix3d mirrorMatrix = Matrix3d.Mirroring(mirrorLine);
  95.  
  96. // Do a geometric mirror on the cloned text
  97.  
  98. mirroredTxt.TransformBy(mirrorMatrix);
  99.  
  100. // Get text bounding box
  101.  
  102. Point3d pt1, pt2, pt3, pt4;
  103.  
  104. GetTextBoxCorners(
  105.  
  106. dbText,
  107.  
  108. out pt1,
  109.  
  110. out pt2,
  111.  
  112. out pt3,
  113.  
  114. out pt4);
  115.  
  116. // Get the perpendicular direction to the original text
  117.  
  118. Vector3d rotDir =
  119.  
  120. pt4.Subtract(pt1.GetAsVector()).GetAsVector();
  121.  
  122. // Get the colinear direction to the original text
  123.  
  124. Vector3d linDir =
  125.  
  126. pt3.Subtract(pt1.GetAsVector()).GetAsVector();
  127.  
  128. // Compute mirrored directions
  129.  
  130. Vector3d mirRotDir = rotDir.TransformBy(mirrorMatrix);
  131.  
  132. Vector3d mirLinDir = linDir.TransformBy(mirrorMatrix);
  133.  
  134. //Check if we need to mirror in Y or in X
  135.  
  136. if (Math.Abs(mirrorLine.Direction.Y) >
  137.  
  138. Math.Abs(mirrorLine.Direction.X))
  139.  
  140. {
  141.  
  142. // Handle the case where text is mirrored twice
  143.  
  144. // instead of doing "oMirroredTxt.IsMirroredInX = true"
  145.  
  146. mirroredTxt.IsMirroredInX = !mirroredTxt.IsMirroredInX;
  147.  
  148. mirroredTxt.Position = mirroredTxt.Position + mirLinDir;
  149.  
  150. }
  151.  
  152. else
  153.  
  154. {
  155.  
  156. mirroredTxt.IsMirroredInY = !mirroredTxt.IsMirroredInY;
  157.  
  158. mirroredTxt.Position = mirroredTxt.Position + mirRotDir;
  159.  
  160. }
  161.  
  162. // Add mirrored text to database
  163.  
  164. //btr.AppendEntity(mirroredTxt);
  165.  
  166. //tr.AddNewlyCreatedDBObject(mirroredTxt, true);
  167.  
  168. //list.Add(mirroredTxt);
  169. mirroredTxt.ToSpace();
  170. tr.Commit();
  171.  
  172. }
  173.  
  174. }
  175. #region p/Invoke
  176.  
  177. public struct ads_name
  178. {
  179.  
  180. public IntPtr a;
  181.  
  182. public IntPtr b;
  183.  
  184. };
  185.  
  186. // Exported function names valid only for R19
  187.  
  188. [DllImport("acdb22.dll",
  189.  
  190. CallingConvention = CallingConvention.Cdecl,
  191.  
  192. EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z")]
  193.  
  194. public static extern int acdbGetAdsName32(
  195.  
  196. ref ads_name name,
  197.  
  198. ObjectId objId);
  199.  
  200. [DllImport("acdb22.dll",
  201.  
  202. CallingConvention = CallingConvention.Cdecl,
  203.  
  204. EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")]
  205.  
  206. public static extern int acdbGetAdsName64(
  207.  
  208. ref ads_name name,
  209.  
  210. ObjectId objId);
  211.  
  212. public static int acdbGetAdsName(ref ads_name name, ObjectId objId)
  213.  
  214. {
  215.  
  216. if (Marshal.SizeOf(IntPtr.Zero) > )
  217.  
  218. return acdbGetAdsName64(ref name, objId);
  219.  
  220. return acdbGetAdsName32(ref name, objId);
  221.  
  222. }
  223.  
  224. [DllImport("accore.dll",
  225.  
  226. CharSet = CharSet.Unicode,
  227.  
  228. CallingConvention = CallingConvention.Cdecl,
  229.  
  230. EntryPoint = "acdbEntGet")]
  231.  
  232. public static extern System.IntPtr acdbEntGet(
  233.  
  234. ref ads_name ename);
  235.  
  236. [DllImport("accore.dll",
  237.  
  238. CharSet = CharSet.Unicode,
  239.  
  240. CallingConvention = CallingConvention.Cdecl,
  241.  
  242. EntryPoint = "acedTextBox")]
  243.  
  244. public static extern System.IntPtr acedTextBox(
  245.  
  246. IntPtr rb,
  247.  
  248. double[] point1,
  249.  
  250. double[] point2);
  251.  
  252. void GetTextBoxCorners(DBText dbText, out Point3d pt1, out Point3d pt2, out Point3d pt3, out Point3d pt4)
  253.  
  254. {
  255.  
  256. ads_name name = new ads_name();
  257.  
  258. int result = acdbGetAdsName(
  259.  
  260. ref name,
  261.  
  262. dbText.ObjectId);
  263.  
  264. ResultBuffer rb = new ResultBuffer();
  265.  
  266. Interop.AttachUnmanagedObject(
  267.  
  268. rb,
  269.  
  270. acdbEntGet(ref name), true);
  271.  
  272. double[] point1 = new double[];
  273.  
  274. double[] point2 = new double[];
  275.  
  276. // Call imported arx function
  277.  
  278. acedTextBox(rb.UnmanagedObject, point1, point2);
  279.  
  280. pt1 = new Point3d(point1);
  281.  
  282. pt2 = new Point3d(point2);
  283.  
  284. var ptX = pt1 + Vector3d.XAxis * ;
  285. var ptY = pt2 + Vector3d.YAxis * ;
  286.  
  287. var lX = new Line(pt1, ptX);
  288. var lY = new Line(pt2, ptY);
  289.  
  290. lX.Color= Color.FromColor(System.Drawing.Color.Green);
  291. lY.Color= Color.FromColor(System.Drawing.Color.Orange);
  292.  
  293. Line line = new Line(pt1, pt2);
  294.  
  295. line.Color = Color.FromColor(System.Drawing.Color.Red);
  296.  
  297. line.ToSpace();
  298. lX.ToSpace();
  299. lY.ToSpace();
  300.  
  301. // Create rotation matrix
  302.  
  303. Matrix3d rotMat = Matrix3d.Rotation(
  304.  
  305. dbText.Rotation,
  306.  
  307. dbText.Normal,
  308.  
  309. pt1);
  310.  
  311. // The returned points from acedTextBox need
  312.  
  313. // to be transformed as follow
  314.  
  315. pt1 = pt1.TransformBy(rotMat).Add(dbText.Position.GetAsVector());
  316.  
  317. pt2 = pt2.TransformBy(rotMat).Add(dbText.Position.GetAsVector());
  318.  
  319. Line linetrans = new Line(pt1, pt2);
  320.  
  321. linetrans.Color = Color.FromColor(System.Drawing.Color.Yellow) ;
  322.  
  323. linetrans.ToSpace();
  324.  
  325. Vector3d rotDir = new Vector3d(
  326.  
  327. -Math.Sin(dbText.Rotation),
  328.  
  329. Math.Cos(dbText.Rotation), );
  330.  
  331. //求垂直于rotDir和normal的法向量
  332. Vector3d linDir = rotDir.CrossProduct(dbText.Normal);
  333.  
  334. double actualWidth =
  335.  
  336. Math.Abs((pt2.GetAsVector() - pt1.GetAsVector())
  337.  
  338. .DotProduct(linDir));
  339.  
  340. pt3 = pt1.Add(linDir * actualWidth);
  341.  
  342. pt4 = pt2.Subtract(linDir * actualWidth);
  343.  
  344. Line linetrans2 = new Line(pt3, pt4);
  345.  
  346. linetrans2.Color = Color.FromColor(System.Drawing.Color.Blue);
  347.  
  348. linetrans2.ToSpace();
  349. }
  350.  
  351. #endregion
  352. }

AutoCad 二次开发 文字镜像的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. 承接 AutoCAD 二次开发 项目

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

  9. AutoCad 二次开发 .net 之创建Table

    我使用了COM对象来在cad2018中创建table表格,需要的ObjectArx开发包可以在官网上下载,并且需要使用.netframework4.6的库才行. 项目里除了引用常规的Cad开发dll, ...

随机推荐

  1. 线性回归 python 代码实现

    本代码参考自:https://github.com/lawlite19/MachineLearning_Python#%E4%B8%80%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%B ...

  2. C语言I博客作业06

    这个作业属于哪个课程 C语言程序设计I 这个作业要求在哪里 作业链接 我在这个课程的目标是 熟悉分支结构 这个作业在那个具体方面帮助我实现目标 可以更完整的编写程序及博客园 参考文献 [参考文献](h ...

  3. 【问题记录】VMware Tools是灰色的,不能安装

    一.VMware Tools简介 VMware Tools 中包含一系列服务和模块,可在 VMware 产品中实现多种功能,从而使用户能够更好地管理客户机操作系统,以及与客户机操作系统进行无缝交互. ...

  4. 虚拟环境:virtualenv与virtualenvwrapper

    前言: 在使用 Python 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题: 亦或者是在开发过程中不想让物理环境里充斥各种各样的库,引发未来的依赖灾难. 此时,我们需要对于不同的 ...

  5. Go语言入门:Hello world

    本文是「vangoleo的Go语言学习笔记」系列文章之一. 官网: http://www.vangoleo.com/go/go-hello-world/ 在上一篇文章你好,Go语言中,我们对Go语言的 ...

  6. window10系统下,彻底删除卸载mysql

    本文介绍,在Windows10系统下,如何彻底删除卸载MySQL...1>停止MySQL服务开始->所有应用->Windows管理工具->服务,将MySQL服务停止.2> ...

  7. 前端技术之:常见前端UI相关开源项目

    Bootstrap https://getbootstrap.com/BootstrapVue provides one of the most comprehensive implementatio ...

  8. 知否知否,VS Code 不止开源

    VS Code, 昨夜始于“开源”,如今“开源”深处渡. 读者看到这句话,也许会有疑惑,为什么两个“开源”都加上了双引号? 其实是笔者有意为之,因为这个两个“开源”的意义有着很大的差别,第一个“开源” ...

  9. Feign设置assessToken

    import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.an ...

  10. 推荐一款Diffy:Twitter的开源自动化测试工具

    1. Diffy是什么 Diffy是一个开源的自动化测试工具,是一种Diff测试技术.它能够自动检测基于Apache Thrift或者基于HTTP的服务.通过同时运行新/老代码,对比运行结果,发现潜在 ...