<s id="mvh2b"><strike id="mvh2b"><u id="mvh2b"></u></strike></s>
    1. <rp id="mvh2b"></rp>

      当前位置:首页 > IT教程

      AutoLisp学习笔记

      时间:2021-08-12 02:52:06来源:金橙教程网 作者:admin8 阅读:50次 [手机版]
       

      autolisp

      【前言】

      最近发现,做CAD二次开发的,要么是计算机相关专业的,没有CAD基础;要么是工程制图出身,不会编程。所以写了这篇博客,AutoLisp学习笔记,根据我的学习经验,旨在给没有基础的你指明学习的方向,让读者少走弯路。

      AutoLISP语言是开发Autocad的主要工具,是LISP语言和AutoCAD有机结合的产物,在AutoCAD的发展及壮大过程中起到了重要的作用。CAD二次开发可以使用VB、LISP和C#语言,CAD均为各种方式开发了平台。之所以使用LISP,是因为经过多年的累积,已经有很多的基础代码,方便程序的开发。

      掌握AutoLISP开发,需要准备如下知识:1、LISP语言?2.AutoCAD基础?3.AutoLISP函数?4.AutoLisp进阶。

      一.?LISP语言相关知识

      跟我们学过的C++?java语言有很大的不同,LISP语言是解释性语言,只有两个基本单位:原子(atom)和列表(List)。这里推荐如下两个博客,前者是一个常用的LISP语言的开发环境,后者是语法学习,配合使用快速学习。这样,半天的时间可以对LISP语言有初步的概念。递归是LISP的精髓,如果看懂链接博客中的所有示例,那么可以进行下一步了。

      【Lisp语言:?在windows下搭建CLisp环境】

      http://blog.CSDN.net/keyboardota/article/details/8237185

      【Lisp入门】

      http://www.cnblogs.com/suiqirui19872005/archive/2007/12/05/984517.html

      二.AutoCAD基础

      AutoCAD博大精深,对于我们这些开发人员,只需了解些基本操作和概念就足够了。个人认为如下几个概念比较重要,部分可以在AutoCAD术语帮助中找到。

      ?? 1、命令

      CAD的操作几乎都可以用命令描述,如创建一个以原点为圆心,半径为100的圆,可用如下几种命令形式完成。CAD中不区分大小写。

      (1)CAD命令?

      命令:circle/c???

      在命令栏里键入c,然后就可以用鼠标在绘图窗口中操作指定圆心和半径。

      (2)?AutoLisp命令

      _$ (setq center ‘(0 0 0))
      _$ (command “circle” center 100)
       
       
      

      (注:_$?是Visual?Lisp控制台的前置符,启动Visual?Lisp的CAD命令是VLIDE,在控制台和CAD命令栏均可使用AutoLisp命令及ActiveX方法。在CAD命令栏查看变量前面加感叹号!)

      学习过前面LISP语言后,应该可以理解setq,command命令其实是AutoLisp函数,即AutoCAD提供给开发人员的Lisp函数。前者为变量设置值,后者是AutoLisp与AutoCAD的接口,可以向AutoCAD命令行直接发送命令和参数。其中列表?‘(0?0?0)和原子?100分别为圆心和半径的参数。如上命令括号不能省略,表示其为函数。

      (3)Active?X方法

      _$ (vl-load-com)
      _$ (setq acad_obj (vlax-get-acad-object))
      _$ (setq acad_document (vla-get-activedocument acad_obj))
      _$ (setq m_space (vla-get-modelspace acad_document))
      _$ (vla-addcircle m_space (vlax-3d-point ‘(0 0 0)) 100)

      Active?X技术通过将AutoCAD的对象显示在外部使用户以各种编程的方式访问AutoCAD对象。Active?X函数?(vla-)?(vlax-)提供了访问对象的各种方法。这里只是引入,说明了CAD命令,AutoLisp命令和ActiveX方法均能对CAD进行操作。

      ?2、图层

      一组具有一定逻辑关系的数据,类似于覆盖在图形上的透明硫酸纸。可以单独查看每个图层,也可以同时查看多个图层。与PS中图层的概念一样,一个绘图可由多个叠加的图层组成,不同的图元可以选择绘制在哪个图层上。通过layer命令(CAD命令)可以生成或者选择图层。

      ?3、选择集。

      顾名思义,选择集就是选择的集合,在绘图窗口中,点击鼠标左键拖动鼠标,所选择的图元构成选择集。在AutoLisp?中可以用?ssget?函数对选择进行处理和过滤,得到自己想要到集合。

      ? 4.?图元对象属性及DXF组代码

      图元,顾名思义,就是CAD中最小的操作单位,如上面画的一个圆,还可以是插入的块。在CAD中,每个图元其实就是一个对象,它们具有各种属性,比如前面画的circle属性包括实体名,实体类型,辅助实体名,所在图层名,圆心坐标,半径等。这些属性都是用DXF组代码的形式写入的。组代码使用LISP语言的点对结构表示图元对象的属性,类似于C++中Map结构。可用entget函数查看。

      _$ (command “circle” ‘(10 286.611 50.8336 0.0)  100)
      _$ (setq ent1 (entlast))
      _$ (entget ent1)
      其中, entlast 函数返回最后的图元,上述返回结果如下:
      ((-1 . <图元名: 7ffff705c20>)	 ;实体名
      (0 . "CIRCLE")	 ;实体类型
      (330 . <图元名: 7ffff7039f0>)	 ;辅助实体名
      (5 . "23A")	 ;实体标号
      (100 . "AcDbEntity")	 ;实体子类说明
      (67 . 0)	 ;空间类型说明
      (410 . "Model")	 ;空间名
      (8 . "0")	 ;图层名
      (100 . "AcDbCircle") 	 ;
      (10 286.611 50.8336 0.0) 	 ;圆心坐标
      (100.000)	 ;半径
       (210 0.0 0.0 1.0))	 ;3D延伸方向

      更多关于DXF可参考AutoCAD的帮助。如果想得到该图元的圆心坐标,使用如下代码。

      _$ (cdr (assoc 10 (entget ent1)))
       (286.611 50.8336 0.0)
      ※拓展:也可以用 ActiveX 的方法进行访问。
      _$ (setq myobject (vlax-ename->vla-object (entlast)))
       #<VLA-OBJECT IAcadCircle 0000000037be66f8>
      _$ (vlax-safearray->list (vlax-variant-value (vlax-get-Property myobject 'center)))
      (286.611 50.8336 0.0)
      这里涉及到 ActiveX 方法和函数,看不懂可先跳过,有概念即可。

      5.?块。

      表示结合起来以创建单一对象的一个或多个对象。常用于块定义或块参照。在块编辑窗口中可增加其属性,在AutoLisp中使用entnext遍历属性。

      6.AutoCAD的自定义配置

      AutoCAD强大的平台可以使用户自定义工作区间,包括菜单,面板,双击动作等等,还能定义新的命令,可以说,AutoCAD的灵活和个性化是软件的精髓,是AutoDesk公司屹立不倒的根基。

      敲击CAD命令:cui,或者【工具】->【自定义】->【界面

      这里可以自定义用户界面,比如想添加一个查看图元属性的菜单选项,可以按如下步骤:

      (1)创建自定义命令?点击命令列表中的五角星,这里使用默认名称“命令1”

      (2)编辑自定义命令的宏,其中^C^C表示连按两下Esc,保证退出其他命令。键入命令:

      ^C^C(entget (SSNAME (SSGET) 0))</span>
      (3)打开菜单栏,在文件菜单中,将命令列表的“命令 1 ”拖动进去。点击确定退出。

      图表?1?CAD自定义界面

      (4)单击选中窗口中任一图元,然后再文件菜单中点击“命令1”,发现命令栏里返回图元的属性信息。

      7.AutoCAD支持文件配置

      类似于Java的环境配置,是程序寻找文件的目录列表。

      三.AutoLisp函数

      参考任一一本关于AutoLisp的书均可。推荐下《AutoCAD?2008?Visual?LISP二次开发入门到精通》,现已绝版(⊙﹏⊙b汗)。AutoLisp函数是二次开发的基础,基本函数不多,是Lisp语言在AutoCAD环境下的扩展,容易掌握。

      四.Visual?Lisp集成开发环境

      CAD命令栏键入 VLIDE 命令弹出VisualLisp开发环境,包括编译器,调试器和其他工具,提高编程效率。控制台窗口可以像AutoCAD命令行那样输入AutoLisp命令,还可以输入Visual LISP命令。

      五.AutoLisp进阶

      ?1.使用ActiveX对象

      我们可以把整个AutoCAD理解为一个对象的模型,包括样式设置对象,组织结构对象,图形显示对象,图元对象,AutoCAD本身也是一个对象。这些对象根据包含关系组成了层次结构,称为对象模型。既然为对象,那么就有属性值和方法。下面我们根据一个例子讲下ActiveX对象的使用方法。我们将使用三种方法完成。

      例:画直线,根据图元名称获得其对象,并得到直线的两个端点。并将直线向x轴负方向挪动1000。

      1.1?ActiveX对象属性的操作

      (1) 选择直线工具,在cad绘图窗口中绘制一条直线

      (2)打开Visual?Lisp,在控制台窗口键入如下代码:

      _$  (vl-load-com)
      _$  (setq line-object (vlax-ename->vla-object (entlast)))
      #<VLA-OBJECT IAcadLine 0000000030624d58>

      若要用ActiveX访问指定的图形对象,则可以先找到对象的图元名,再将这个名称转化为VLA对象,之后就可以按照访问VLA对象的方法访问了。通过上面两行代码,我们就得到了刚刚画的直线的对象,并保存在变量line-object中。

      右键变量line-object,选择【检验】。弹出【检验】窗口,这里我们可以看到这个变量的多个属性。其中<StartPoint>和<EndPoint>便是线段的起点和终点。这里我们看到<EndPoint>值为#<variant?8197...>,这是一种ActiveX型的数据类型,术语“变体”。变体是应用在ActiveX对象操作中使用的数据类型,可以通过内置的函数与AutoCAD中的数据相互转化,下面我们将看到应用。双击<EndPoint>,弹出子窗口,我们可以看到该变体的值是一个元素类型为Double的#<safearray...>,Safearray(安全数组)也是一种ActiveX数据类型。双击safearray,弹出子窗口我们终于看到终点坐标(1007.6?3440.77?0.0)。

      图表?2?ActiveX对象检验

      接下来我们使用Lisp代码完成读取工作

      _$ (setq endp (vla-get-endpoint line-object))
      #<variant 8197 ...>
      _$ (setq endp2 (vlax-variant-value endp))
      #<safearray...>
      _$ (setq endp3 (vlax-safearray->list endp2))
      (1007.6 3440.77 0.0)

      其中vla-get-endpoint,vlax-variant-value,vlax-safearray->list是AutoLisp函数。同样如法炮制得到起点的坐标值:

      _$(setq startp3 (vlax-safearray->list (vlax-variant-value (vla-get-startpoint (vlax-ename->vla-object (entlast))))))
      (234.156 3400.91 0.0)

      接下来设置新的坐标

      _$ (setq newEndP (list (- (nth 0 endp3) 1000) (nth 1 endp3) (nth 2 endp3)))
      (7.6 3440.77 0.0)
      _$ (setq newStartP (list (- (nth 0 startp3) 1000) (nth 1 startp3) (nth 2 startp3)))
      (-765.844 3400.91 0.0)

      接下来将新的坐标写入该对象,写入函数vla-put-?要求写入参数应当为变体类型,所以我们创建了两个安全数组,NewEndP2&NewStartP2。

      _$ (setq NewEndP2 (vlax-make-safearray vlax-vbDouble '(0 . 2)))
      #<safearray...>
      _$ (vlax-safearray-fill NewEndP2 NewEndP)
      #<safearray...>
      _$ (setq NewStartP2 (vlax-make-safearray vlax-vbDouble '(0 . 2)))
      #<safearray...>
      _$  (vlax-safearray-fill NewStartP2 NewStartP)
      #<safearray...>
      _$ (vla-put-startpoint line-object NewStartP2)
      nil
      _$ (vla-put-endpoint line-object NewEndP2)
      Nil

      同样地,我们可以不用ActiveX,而是采用AutoCAD?内部命令来完成上述工作。

      _$(setq ent1 (entget (entlast)))
      _$(setq oldEndp (assoc 11 ent1))	;终点坐标DXF组码值为11
      _$ (setq oldStartp (assoc 10 ent1))	;起点坐标DXF组码值为10
      _$ (setq newEndp (list 10 (- (nth 1 oldEndp) 1000) (nth 2 oldEndp) (nth 3 oldEndp)))
      _$ (setq newStartp (list 10 (- (nth 1 oldStartp) 1000) (nth 2 oldStartp) (nth 3 oldStartp)))
      _$ (setq ENT1 (subst newEndp oldEndp ENT1))
      _$ (setq ENT1 (subst newStartp oldStartp ENT1))
      _$ (entmod ENT1)

      可能这时你就有疑问了,既然两种办法都可改变图元的属性,那还用ActiveX干嘛。其实相比于其他AutoCAD?api环境,ActiveX接口技术速度快,效率高,随CAD安装,便于使用。另外ActiveX的对象交互技术使得CAD可与外界应用程序交互,拓宽了CAD开发的应用范围。

      1.2?ActiveX对象属性的操作

      Visual?Lisp提供了Vlax-invoke-method函数来调用ActiveX的方法。使用的时候要注意将参数转化为ActiveX型,除非参数的默认分配类型(见将数据类型转换为ActiveX型)正好为所需的类型。对于上面的line-object,我们如何知道该对象所支持的ActiveX方法呢,下面提供个人经验。首先使用vlax-dump-object函数列出line-object所支持的方法。

      _$ (vlax-dump-object line-object t)
      ; IAcadLine: AutoCAD Line 接口
      ;特性值:
      ;   Angle (RO) = 0.620333
      ;   Application (RO) = #<VLA-OBJECT IAcadApplication 000000013f993318>
      ;   Delta (RO) = (1361.03 972.338 0.0)
      ;   Document (RO) = #<VLA-OBJECT IAcadDocument 000000002fb96bc8>
      ;   EndPoint = (1458.44 1051.22 0.0)
      ;   EntityTransparency = "ByLayer"
      ;   Handle (RO) = "236"
      ;   HasExtensionDictionary (RO) = 0
      ;   Hyperlinks (RO) = #<VLA-OBJECT IAcadHyperlinks 0000000039a12ad8>
      ;   Layer = "0"
      ;   Length (RO) = 1672.68
      ;   Linetype = "ByLayer"
      ;   LinetypeScale = 1.0
      ;   Lineweight = -1
      ;   Material = "ByLayer"
      ;   Normal = (0.0 0.0 1.0)
      ;   ObjectID (RO) = 42
      ;   ObjectID32 (RO) = 42
      ;   ObjectName (RO) = "AcDbLine"
      ;   OwnerID (RO) = 43
      ;   OwnerID32 (RO) = 43
      ;   PlotStyleName = "ByLayer"
      ;   StartPoint = (97.4054 78.8798 0.0)
      ;   Thickness = 0.0
      ;   TrueColor = #<VLA-OBJECT IAcadAcCmColor 0000000039a12890>
      ;   Visible = -1
      ;支持的方法:
      ;   ArrayPolar (3)
      ;   ArrayRectangular (6)
      ;   Copy ()
      ;   Delete ()
      ;   GetBoundingBox (2)
      ;   GetextensionDictionary ()
      ;   GetXDATa (3)
      ;   Highlight (1)
      ;   IntersectWith (2)
      ;   Mirror (2)
      ;   Mirror3D (3)
      ;   <span style="color:#ff0000;">Move (2)</span>
      ;   Offset (1)
      ;   Rotate (2)
      ;   Rotate3D (3)
      ;   ScaleEntity (2)
      ;   SetXData (2)
      ;   TransformBy (1)
      ;   Update ()

      这里我们看到有个名字为Move的方法,猜想其可以完成图元的移动,是否如此呢,查看帮助中的“AutoCAD?ActiveX?and?VBA?references”部分,查找Move?Method,确实是我们预想的那样。接下来我们使用这个函数同样完成将直线向x轴负方向挪动1000的工作。Move方法接受两个参数,Point1&Point2,分别表示移动向量的起点和终点。显然这里Point1&Point2的坐标分别为(0?,?0?,?0)和?(-1000?,?0?,?0)。参数类型要求为Variant?(three-element?array?of?doubles),我们先构造两个double类型的safearray,然后转化为变体(Variant?)类型。(转化为变体类型这一步并非必须,因为safearray会被强制转化为Variant)最后作为实参代入函数,看能否同样完成前面的工作。

      图表?3?Move方法帮助

      _$  (setq Point1 (vlax-make-safearray vlax-vbDouble '(0 . 2)))
      #<safearray...>
      _$  (setq Point2 (vlax-make-safearray vlax-vbDouble '(0 . 2)))
      #<safearray...>
      _$  (vlax-safearray-fill Point1 (list 0 0 0))
      #<safearray...>
      _$  (vlax-safearray-fill Point2 (list -1000 0 0))
      #<safearray...>
      _$ (setq Point1 (vlax-make-variant Point1))	 ;;转换为变体类型,非必须
      #<variant 8197 ...>
      _$ (setq Point2 (vlax-make-variant Point2))	 ;;非必须
      #<variant 8197 ...>
      _$ (vlax-invoke-method line-object "Move" Point1 Point2)
      Nil

      然后将窗口切换到AutoCAD绘图窗口,直线确实按照我们预想的一样,又往x轴负方向移动了1000单位。

      总结:对于某一ActiveX对象,使用vlax-dump-object函数可以列出该对象的属性值和适用的ActiveX方法。对属性值的操作,可以采用vla-get和vla-put为前缀的函数。ActiveX方法就比较复杂,若要查找相应的操作函数的使用方法,可以参考AutoCAD帮助中的“AutoCAD?ActiveX?and?VBA?references”部分。并应用vlax-invoke-method方法调用ActiveX对象的方法。CAD2013版本以后,VBA开发不再随软件安装,所以帮助部分也不容易找到了。http://entercad.ru/acadauto.en/?网站可供参考使用。

      ?2.ActiveX对象交互

      在Visual?Lisp环境中,也可以使用其他应用程序的ActiveX对象。笔者在开发的时候,遇到xml和CAD信息交互的问题,上网搜索,发现没有解析XML的LISP库,如果自己写XML解析,势必大大影响项目进展。终于在ActiveX对象中找到灵感,下载了一个XML的ActiveX控件,加载到自己的程序里完成项目开发。(见我的另一篇博客,AutoLisp中XML解析方案)

      【欢迎转载,请注明出处】

      相关阅读

      AutoLISP笔记——常用代码片断

      1、字符串按指定分隔符分隔 ;;;功能:字符串按指定分隔符分隔 ;;;(split "1,,255280.791,3743764.732,2786.206" ",") ;;;返回:("1"

      分享到:

      IT相关

      程序相关

      推荐文章

      热门文章

      东北老女人嫖老头视频_无遮挡H肉动漫视频在线观看_欧美牲交a欧美牲交aⅴ另类_狼人乱码无限2021芒果