【前言】

最近发现,做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. PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call

    您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...

  2. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  3. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  4. 2020年Yann Lecun深度学习笔记(下)

    2020年Yann Lecun深度学习笔记(下)

  5. 2020年Yann Lecun深度学习笔记(上)

    2020年Yann Lecun深度学习笔记(上)

  6. 知识图谱学习笔记(1)

    知识图谱学习笔记第一部分,包含RDF介绍,以及Jena RDF API使用 知识图谱的基石:RDF RDF(Resource Description Framework),即资源描述框架,其本质是一个 ...

  7. 计算机基础知识第十讲,计算机文化基础(第十讲)学习笔记

    计算机文化基础(第十讲)学习笔记 采样和量化PictureElement Pixel(像素)(链接: 采样的实质就是要用多少点(这个点我们叫像素)来描述一张图像,比如,一幅420x570的图像,就表示 ...

  8. Go 学习推荐 —(Go by example 中文版、Go 构建 Web 应用、Go 学习笔记、Golang常见错误、Go 语言四十二章经、Go 语言高级编程)

    Go by example 中文版 Go 构建 Web 应用 Go 学习笔记:无痕 Go 标准库中文文档 Golang开发新手常犯的50个错误 50 Shades of Go: Traps, Gotc ...

  9. MongoDB学习笔记(入门)

    MongoDB学习笔记(入门) 一.文档的注意事项: 1.  键值对是有序的,如:{ "name" : "stephen", "genda" ...

最新文章

  1. set,存放不重复数据的集合类型
  2. Android普及入门
  3. golang panic的错误回收和简单的使用场景
  4. [导入]ASP.NET 2.0中Page事件的执行顺序
  5. BZOJ 1024: [SCOI2009]生日快乐 dfs
  6. python 熊猫钓鱼_Python数据结构与算法之使用队列解决小猫钓鱼问题
  7. 自动化测试——unittest生成HTML测试报告
  8. 密码库LibTomcrypt的内容介绍及分析
  9. android 公式编辑器,公式编辑器
  10. C语言书籍阅读-读书笔记--《C专家编程》
  11. 微信开发获取签名wx.config
  12. 你不是菜鸟2:他为什么没过试用期
  13. 精品微信小程序ssm电影院购票+后台管理系统|前后分离VUE
  14. PMP考试如何获取PDU
  15. 微信小程序留言板设计
  16. NVMe SSD测试为何要先做预处理?
  17. 水源热泵系统的优点和缺点有哪些?
  18. python编程:总结了一些高效使用 PyCharm 技巧,(三)
  19. mysql mmm 官方_mysql mmm
  20. cs231n:assignment2——Q4: ConvNet on CIFAR-10

热门文章

  1. XPS测试表面及表面分析技术
  2. 解决数据库插入中文变问号问题
  3. Silverlight游戏研发手记:(一)差集运算在SLG战斗范围设定中的应用
  4. win7系统下比较好用的桌面日程安排提醒软件是什么?
  5. linux 运行ca.crt,linux下生成https的crt和key证书
  6. echarts设置饼状图的标示线以及标示文字的颜色等相关样式
  7. 天泉湖酒店式养生社区服务中心漏电火灾监控系统的设计与应用
  8. 区块链技术 英文(BlockChain Terminal)简称BCT ——区块链终端
  9. [TJOI2013]黄金矿工解题报告
  10. Java编写udf函数