本文是
AutoLisp
从零开始入门的指南。
AutoLisp
语言是
AutoCAD二次开发
的重要语言。只要有最基本的编程基础,通过本教程都可以快速地掌握
AutoLisp
语言的应用方法。
本文首先对
AutoLisp
语言做了简明的介绍,然后直接进入实例部分,通过实例脚本的解读和联想来快速介绍
AutoLisp
的使用方法。这样做的好处是易于上手,易于理解,但是缺乏系统性。读者可以在读完本教程之后再系统性地读
AutoLisp
的开发者文档,这样就可以实现从入门到精通。
本教程共分为 4 个部分。在本文中,主要编写了一个简点的三角函数圆自动绘图脚本,用于介绍以下内容
defun
函数,用于定义用户命令。
setq
函数,用于为变量赋值。
getint
函数和一系列相关的
get
类输入函数,用于程序与用户交互。
if
函数,用于条件判断。
command
函数,用于调用
AutoCAD
命令。
osnap
函数,用于捕捉点。
rtos
函数和一系列字符串转换函数,用于字符串与数字转换。
polar
函数和一系数相关的图形处理函数,用于确定点的位置、距离、角度等。
下面,让我们开始吧!
AutoLisp 简介
什么是 AutoLisp 语言
AutoLisp 语言有什么用
通过
AutoLisp
语言编程,可以节省
AutoCAD
使用者的很多时间。其作用主要体现在以下几个方面
AutoLisp
语言是
AutoCAD
软件最直接、最简单、最易用的编程语言。
AutoLisp
语言可以完全取代
AutoCAD
的全部命令,同时还可以提供更丰富的功能。
AutoLisp
语言作为一种编程语言满足一些编程语言的结构和功能。
AutoLisp
在批量操作、参数化绘图方面有重要作用。
AutoLisp
有强大的图形操作能力。
AutoLisp 语言的特点
AutoLisp
语言是一种函数式语言,一切都以函数给出,没有语句的概念和语法结构。
AutoLisp
语言是表处理语言,函数的调用是通过表来完成的。表通过圆括号
()
来定义。
AutoLisp
的程序和数据都是表结构,所以程序可以当作数据来处理,数据也可以当作程序来处理。
Hello, World!
略去冗长的介绍,我们通过实例,由浅入深地学习
AutoLisp
吧!
第一段 AutoLisp 脚本
打开
AutoCAD
,在控制台(即输入命令的文本框)中输入
1 |
(alert "Hello, world!") |
回车提交,发现弹出一个警告对话框,里面写着
Hello, world!
。
这就是你的第一段 AutoLisp 脚本。怎么样,简单吧!
正如上一章中所说,本程序中我们使用
AutoLisp
语言只写了一行语句。这行语句被圆括号
()
括起来,形成了一个所谓的
表
(也就是我们所说的“表处理语言”中的“表”)。这个
表
中有两个元素,
alert
和
"Hello, world!"
。 其中
alert
是函数名,表示在这个语句中,我们要调用
alert
这个函数。
"Hello, world!"
是一个字符串(字符串是一种数据类型)。这个字符串作为
alert
这个函数的参数。程序在解释这句话时,调用
alert
函数,它的功能是弹框输出一条警告信息,内容为其后根随的字符串。因此产生了您看到的对话框。
通过 AutoCAD 命令来运行
首先,用文本编辑软件新建一个文本文件,命名为
hello_world.lsp
。这里推荐使用
Visual Studio Code
。也可以根据您的喜好选择
Notepad++
、
UltraEdit
等文本编辑软件,不要使用 Windows 操作系统自带的
记事本
软件。在文本文件中输入如下代码
1 |
(defun c:hello(/) |
打开
AutoCAD
,输入命令
1 |
appload |
在弹出的对话框中选择刚才创建的
hello_world.lsp
文件,单击
load
,忽略安全提示。在控制台中出现
1 |
hello_world.lsp successfully loaded. |
说明脚本已经成功加载。这时输入我们在脚本中定义的命令
1 |
hello |
用回车或空格提交,发现弹出了对话框,内容显示:Hello, world!
在本例中,
defun
定义了一个
lisp函数
。在
AutoLisp
中,以
c:
开头的函数表示注册一条可执行的命令。本例中
c:hello
就表示注册一个命令
hello
。
alert
函数的用法和上一小节中所述相同。
添加用户交互
创建一个新文件
hello_name.lsp
,键入如下代码
1 |
(defun c:hello(/ name) |
重新加载,在控制台中输入
1 |
hello |
会发现出控制台中出现提示
1 |
What's your name? |
1 |
Jack |
回车,控制台中输出字符串
1 |
"Hello, Jack" |
在本例中,对函数的定义多了一个参数
name
。这一参数通过
getstring
命令从控制台读入,再通过
setq
命令存储在变量
name
中。再通过
strcon
函数将两个字符串连接起来,最后用
write-line
在控制台输出。
以上是一些最简单的入门。下面我们通过几个实例由浅入深地学习
AutoLisp
语言。建议读者每一个实例的代码都自己输入并测试一遍。这样读完本文后就基本可以掌握
AutoLisp
的使用方法了。
绘制三角函数圆
在这一章中,我们通过一个绘制三角函数圆的程序来学习
AutoLisp
最重要的几个函数。它们是
defun
函数,用于定义用户命令。
setq
函数,用于为变量赋值。
getint
函数和一系列相关的
get
类输入函数,用于程序与用户交互。
if
函数,用于条件判断。
command
函数,用于调用
AutoCAD
命令。
osnap
函数,用于捕捉点。
rtos
函数和一系列字符串转换函数,用于字符串与数字转换。
polar
函数和一系数相关的图形处理函数,用于确定点的位置、距离、角度等。
脚本功能
脚本代码
1 |
(defun c:tricircle(/ rad) |
打开
AutoCAD
,键入命令
1 |
appload |
选择代码所保存的文件加载。成功后,键入
1 |
tricircle |
根所提示,输入所求弧度:1,回车,发现图形已经画好,如下图所示。
注意,请关闭捕捉功能。否则某些点可能被错误捕捉。
代码解读
defun
函数
首先,定义一个
lisp
函数,使用的是
defun
函数。使用方法为
1 |
(defun [函数名](/ [局部变量1] [局部变量2]) [表达式1] [表达式2] ... ) |
函数名:
函数名在定义时,如果采用
c:
开头,表示注册一个
AutoCAD
命令。此后可以在控制台中直接输入
c:
后面的命令来调用这一函数,而无输再输入
AutoLisp
代码。
局部变量:
局部变量的含义是,这一变量在函数执行完毕后就被释放。通常把用户输入的变量设为局部变量。这里我们把用户输入的弧度值
rad
设为局部变量。
表达式: 当函数被调用时,表达式的内容被执行。
setq
函数
在函数的定义中,我们首先用了
setq
函数。这个函数用于为变量赋值。使用方法为
1 |
(setq [变量名] [值]) |
变量名: 即要被赋值的变量名。
值: 即要赋的值。
在
AutoLisp
中,有以下几种数据类型
SETQ
赋值
用双引号,支持转义
分为标准表、引用表、点对
文件描述符
文件操作使用
PICKSET
存储一系列 AutoCAD 实体
ENAME
存储一个 AutoCAD 实体
在
setq
语句中可以把上述任意数据类型赋给变量。
setq
语句还支持多个变量的同时赋值,方法为
1 |
(setq [变量名1] [值1] [变量名2] [值2] ...) |
getreal
函数和其它 GET 类函数
在本例的
setq
语句中,还用到了
getreal
函数。这个函数在执行时,由用户在控制台中输入数字,并返回这个数字。用法为
1 |
(getreal [字符串]) |
这里的字符串为引导用户输入的提示字符。
与
getreal
函数相似,还有一些用户输入用的函数,列举如下。
在本例中,还使用了一个默认值输入的方法。
get
类函数本身是不支持默认值的,但是我们通过对用户输入空值情况的处理来实现默认值输入。这里我们用了一个
if
函数。
if
函数
1 |
(if [布尔表达式] [条件为真执行] [条件为假执行]) |
在
AutoLisp
中,数学表达式和布尔表达式用以下几种常见形式
此外还有一些常用的数学运算函数,如
log
、
sin
、
max
等,请读者自行尝试。
在本例中,如果用户没有输入,则
getreal
函数返回 nil,触发
getq
表达式,给变量
rad
赋值为 1.0。
command
函数
command
函数是
AutoLisp
中最重要的函数。它可以调用所有
AutoCAD
命令。用法如下
1 |
(command [命令名] [参数1] [参数2] ...) |
命令名:
即
AutoCAD
命令的名字,用一个字符串来表示,也就说要用双引号引起来。在本例中,我们使用了
"line"
、
"text"
、
"circle"
、
"arc"
几个命令。
参数: 即在执行命令时,所需要用户输入的参数。
以
"line"
命令为例,首先我们要确定输入哪些参数。打开
AutoCAD
,在控制台中输入
1 |
line |
回车,看到提示输入一个点,这就是我们要给出的第一个参数。
按提示输入点后,又提示再输入一个点,这是我们要给出的第二个参数。
输入好第二个点后,提示再输一个点,会再画一条线,这时我们不想继续画,输入回车结束命令。这是我们要给出的第三个参数。
这样,我们就确定了要输出的三个参数,分别是两个点和一个回车。因此本例中,我们用两个列表来表示点,用一个空字符串来表示回车(
AutoLisp
的约定)。得到
1 |
(command "line" '(-120 0) '(120 0) "") |
其它命令的用法也类似,请读者自己体会。
列表
上一节
的
command
命令中需要输入点,我们用列表输入点的坐标的方式来完成。本节介绍列表的使用方法。
在 数据类型 部分,我们介绍过列表分为标准表、引用表和点对,这里我们详细解释它们各自的用法。
标准表:
就是
AutoLisp
作为一种
表语言
所用的最常见的表。在这种表中,第一个元素为函数名,后面的元素为函数的参数。程序在解释时,会执行函数名所代表的函数。
引用表: 是一种特殊的表,其第一个元素不是函数名,不作为函数执行。与其它编程语言中的数组类似。
引用表有两种定义方式。当其元素都是定值时,可以在圆括号前加一个单引号表示。例如
1 |
'(120 0) |
这个用法在本例的第 4、5、6、7 等行有体现。
当其元素中有变量时,不应采用这种形式,而可以采用
list
函数来创建,其使用方法为
1 |
(list 120 0) |
这个用法在本例的 16、17 行中有体现。
二者的结果是相同的。
点对: 点对是一种只有两个元素的表,在列表中间用一个圆点隔开。例如
1 |
'(120 . 0) |
常用于构建关联表。
对于列表中元素的提取,有两个函数
car
和
cdr
及它们的组合。
car
函数用于取出列表中的第一个数。例如
1 |
(setq a '(1 2)) |
这时
b
的值为 1。
cdr
函数用于排除列表中的第一个数,返回一个新列表。例如
1 |
(setq a '(1 2)) |
可以看到,
b
返回的值为
(2)
,而
d
返回的值为
2
。这就是引用表与点对的区别。点对只有两个元素,所以用
cdr
返回的不是表,而是它的右元素。而引用表中
cdr
返回的是只有一个元素的表。
car
和
cdr
可以结合在一起递归调用。举例来说,函数
cadr
就是先执行一次
cdr
,去掉第一个元素,再执行一次
car
,取出第一个元素。也就是取出原表中的第二个元素。这在提取点的坐标时非常有用。例如
1 |
(setq p '(1 2 3)) |
x
、
y
、
z
分别为点
p
的三个坐标值。
在本例的第 14、15 行有对这些函数的应用。
osnap
函数
在本例第 10、11 行中,使用了
osnap
函数,用于临时捕捉点。用法为
1 |
(osnap [点] [捕捉模式]) |
它的用法和
AutoCAD
中临时捕捉点时的用法基本相同。其中
捕捉模式
包括
rtos
等字符串转换函数
rtos
是把实数转化为格式化的字符串的函数。我们知道,实数有多种表示方法,该函数支持多种格式化字符串的表示。最常用的是十进制模式。用法为
1 |
(rtos [实数] 2 [小数位数]) |
在本例的第 13、16、17 行有这个函数的应用。
其中 2 就表示十进制模式,对于其它模式不是很常用,本例中不作介绍。
对于数字和字符串的转换是经常需要用到的。这里介绍一些其它常用的字符串转换函数。
将整数转为字符串 (itoa 100) 返回 “100” 将字符串转为整数 (atoi “12.6”) 返回 12(截尾取整) 将字符串转为实数 (atof “12.6”) 返回 12.6
polar
等图形处理函数
在本例第 10、11 行用了
polar
函数。
polar
是用极坐标的方式求点坐标的函数,用法为
1 |
(polar [基点] [方向角] [距离]) |
返回一个新的点。这在确定点的方位的时候常常用到。
类似的常用图形处理函数列举如下
distance 求两点距离 (distance [点 1][点2]) angle 求两点连线与 x 轴夹角 (angle [点 1][点2]) inters 求两直线交点 (inters [线 1 端点 1][线1端点2] [线 2 端点 1][线2端点2] nil)
其中,
inters
后面的
nil
表示可以在延长线上相交。