【越飞越高讲堂9】如何像photoshop那样---CAD中的平面几何变换及其矩阵
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal> </P><P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>大家都知道,在<SPAN lang=EN-US>photoshop 中,对图像的某部分如果要实施变换,是很方便的,按下ctrl+T 之后,就会一个矩形外框,对矩形外框变换时,也对图像实施了变换。Photoshop是光栅格式的图,Coreldraw 等之类的矢量编辑软件,同样也有相似的功能。
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>在<SPAN lang=EN-US>CAD中要完成这样的变换,可能需要几个步骤。而且对于圆,椭圆之类的想要实现其准确的错切变换,就很困难。今天我完成了这样的一个lisp程序,放在这里与大家讨论一下。
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>先简单介绍一下仿射变换。<SPAN lang=EN-US>
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>仿射变换是一种线性变换,其变换方程为<SPAN lang=EN-US>:<SPAN style="mso-spacerun: yes"> X=a11*x+b11*y+c11</SPAN>,Y=a12*x+b12*y+c12
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="MARGIN: 0cm 0cm 0pt" class=MsoNormal>包括了我们平常说的正交变换,旋转,缩放,不等比缩放,错切变换,镜像变换等等。<SPAN lang=EN-US>
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="MARGIN: 0cm 0cm 0pt" class=MsoNormal>这是一种线性变换群,其中有很多不变量。例如:<SPAN lang=EN-US> 1,平行性保持不变,2,同素性。3,简比,4,结合性等等。二次曲线变换也有不变量:椭圆变换之后仍然是椭圆,如此等等。
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>因为<SPAN lang=EN-US>CAD执行的是矢量数据,对线或曲线实施了变换后,实际是对其方程的变换,不是对像素的变换,因而必须了解其变换后的方程式。现先看看变换矩阵:
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>((a 0 0) (0 b 0) (0 0 1))是比例变换;<SPAN lang=EN-US>((1 0 0) (0 1 0) (0 0 s))是等比变换
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>((1 0 0) (c 1 0) (0 0 1))是沿<SPAN lang=EN-US>x错切变换,((1 b 0) (0 1 0) (0 0 1))是沿Y错切变换
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>((cos(a) sin(a) 0) (-sin(a) cos(a) 0) (0 0 1))是旋转变换。<SPAN lang=EN-US>
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>((1 0 0)(<SPAN lang=EN-US>0 1 0)(g h 1))是平移变换
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>可以把这个矩阵推广到<SPAN lang=EN-US>4X4阶的变换,(包括了透视变换)我不在此赘述。
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>开始的时候我想的简单以为用<SPAN lang=EN-US>vla-transformby就可以实现了,却不知这个函数实现的变换很有限,连不等比变换都实现不了,那就有点形同虚设了。为此,我参阅了一些书籍,这些日子断断续续地完成了第一步,也是很关键的一步。那就是基本能实现了仿射变换,(主要对错切变换较为有用),从理论上来说,这个变换能实现基本所有的几何变换,但那样可能比较麻烦。
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>然后我加载了一个反应器<SPAN lang=EN-US>( 很多代码来源于lisp的教程-----gp: path)
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>用法如下<SPAN lang=EN-US>: 加载程序(两个都要加载 reactor5.lsp, transXY.lsp)后,运行test
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal><SPAN style="mso-spacerun: yes"> </SPAN>如果不用反应器,就用<SPAN lang=EN-US>t1命令</SPAN></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal> </P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">选中物体之后,出现包围物体的外框,当对这个外框的夹点拉伸,就能实施仿射变换<SPAN lang=EN-US>(例如错切变换),对这个外框实行其他CAD命令,如move等命令时候,反应器将不再与这个外框联系,当删除外框后,反应器也将移除。
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>代码较长,故未贴出,在附件中,我也不会搞演示,所以只能看提示了。<SPAN lang=EN-US>
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal>这个代码还很不完善,正在向下一步目标迈进<SPAN lang=EN-US>:<SPAN style="mso-spacerun: yes"> </SPAN>把反应器链接到不等比变换中去,再接下来就是平移变换。再就是链接到CAD的基本变换命令等等。(一步比一步更简单),在此过程中我希望能听听大家的看法和建议。</SPAN></P></SPAN>
<P></P>
<P></P>
<P></P>
<P> </P> 尘缘一生 发表于 2020-9-6 02:43
希望高大帅对:角度1,角度2 做些解释,另外,最后集成程序完成了吗?
角度1,角度2是根据错切变换的矩阵计算公式得到的,你可以参考下面的帖子:
https://blog.csdn.net/yinhun2012/article/details/79649089
https://blog.csdn.net/jia20003/article/details/39994823
其实,程序已经集成完毕。但近来一直忙于工作的事情,也就没发表了。 highflybir 发表于 2006-12-29 11:25
to byghbcx:第一个程序是关于错切变换的,reactor-shift.lsp,带反应器;第二个程序是不带反应器的错切变换, ...
希望高大帅对:角度1,角度2 做些解释,另外,最后集成程序完成了吗? 原来贱人工具箱的这个功能来自您这 <p>今天再次完成了对物体的X,Y方向任意比例(可以为负值,但不能为零)变形。</p><p>用法 :加载lisp,运行test </p><p>选中物体之后,出现包围物体的外框,当对这个外框的夹点拉伸,就能实施比例变换<span lang="EN-US">(包括不等比变换),对这个外框实行其他CAD命令,如move等命令时候,反应器将不再与这个外框联系,当删除外框后,反应器也将移除。</span></p><p></p><p></p><p>接下来的工作便是加对话框,把两个变换融合到一起,使之变成一个完整的程序。</p><p>其实关于这个程序,里面包含的一些程序也是常用的,例如:</p><p>1、求包围物体的最大外框</p><p>2、求物体的错切变换</p><p>3、求物体的不等比变换</p><p>4、对反应器的用法。</p><p>5、建立选择集的匿名块。</p><p>还有一些来源于教程gp:path--花园小路(一篇很不错的lisp教程)中的一些代码,有些适用的程序,如极小数视为零,点表转化为activeX方式的列表,等等。</p> <p>看了highflybird的程序,真是佩服,这需要强大的数学功底和理论水平,但愿你的程序能在下一版的ACAD中加进去,这个功能确实很强大。您是建筑师,这在建筑平面表达上,很有创意,特别是在建筑平面相互叠加时,画垂直交通时很有用,还有在规划图的表达上很好,如地上空间、地面空间、地下空间的开发利用图纸表达,管线图的叠加等等。</p><p>不过,上面的程序对错切变换加入反应器,以及任意形壮的变换还没实现.是不是没有发出来?</p> <p><font face="Verdana" color="#61b713"><font color="#000000">to </font><strong>byghbcx:</strong></font></p><p>第一个程序是关于错切变换的,reactor-shift.lsp,带反应器;</p><p>第二个程序是不带反应器的错切变换,transXY.lsp;</p><p>第三个程序是关于比例变换的,reactor-scale.lsp,带反应器;</p><p>任意形状的比例变换已经实现,但任意形状的错切变换还没完全实现,现在实行错切变换的物体有:</p><p>polyline,arc,circle,ellipse,line,point,应付一般问题已经足够。下一步的目标是实现对物体spline,text,dim,block等等也能仿射变换。现在遇到的困难是spline样条曲线的方程我不知道,查阅了书籍和网站,依然不得其法。</p><p>最终要加入菜单或者对话框以供选择(这还比较好办),以及实现射影变换(透视变换)。希望大家能提供思路或者资料给我,谢谢!</p> <p>支持你,我今天也试着对text,solid,spline进行仿射变换.对mtext没能转换.spline参照pline的变换.有时候不太理想.</p> 本帖最后由 作者 于 2006-12-30 17:57:43 编辑 <br /><br /> <p>感谢<font face="Verdana" color="#61b713"><strong>byghbcx</strong><font color="#000000">!</font></font></p><p><font face="Verdana"> 很好,我本来要打算写这几CAD类型的代码的,你替我写了,谢谢你!特别是对文字的变换,你写的很好!</font></p><p><font face="Verdana"> 另外我感觉可能有一种比较普遍的方法,能够对付CAD所有类型,(因为是仿射变化,应该与UCS 用户坐标系有关,但是一下子还没有想出来).<br/> 下面是加了反映器后文字变换的效果:</font></p> 本帖最后由 作者 于 2006-12-30 18:19:33 编辑
VBA版的那个VBA程序效果如何?哪些地方需要改进?请指教。谢谢! 本帖最后由 作者 于 2006-12-30 18:41:16 编辑 <br /><br /> <p></p><p>to ahlzl版主:</p><p>其实这两个变换区别如上:左图是我的,右图是你的。如果输入同样的角度的话,(譬如保持x方向不变,y错切30度),可以看出我的错切变换保证了x的比例没有发生变化,你的发生了变化。但你的程序能够适合所有的CAD对象,我曾经研究了你的方法,想把你的方法编成lisp但是没有成功。</p><p>希望ahlzl能帮我把VBA的方法转化为Vlisp的方法,谢谢!</p> <p>to ahlzl版主:</p><p>我怎么没找到VBA版的那个VBA程序,请给一下链接地址,谢谢!</p> <p><a href="http://bbs.mjtd.com/forum.php?mod=viewthread&tid=55956">http://bbs.mjtd.com/forum.php?mod=viewthread&tid=55956</a></p><p><a href="http://www.mjtd.com/Html/News/mcNews/94520060213175331.htm">http://www.mjtd.com/Html/News/mcNews/94520060213175331.htm</a></p>