文章目录
一、概述
1.1 简介
- 简介:cad 二次开发语言,后缀名
*.lsp
适用于编写小工具,不适用大量数据或者需要大量计算的场景,编译后后缀名为*.vlx
- 优点:所有cad版本均通用,不像arx或者其他只针对固定版本
- 缺点:不适合处理大量计算或图元场景,超过1000个单元即有轻微等待卡顿,软件加密困难
1.2 打开编辑器
- cad命令行输入:
vlisp
- cad菜单:管理–>visual lisp 编辑器
- cad菜单:工具–> auto lisp–>visual lisp 编辑器
1.3 调试页面
- 主编辑窗口
- 跟踪变量值
- 分步调试
二、数据类型
- 常量:数字、nil、t、null
- 变量
数据类型 意义 数据类型 意义 浮点型 REAL 整型 INT 字符串 STR 表 LIST 文件描述符 FILE 符号 SYM 选择集 PICKSET 图元名 ENAME 内部LISP函数 SUBR 外部ads函数 EXSUBR - 查看类型语句:
(type item)
三、函数
- 地位:lisp中万物皆函数,函数均用括号括起来
- 返回值:默认返回函数内
最后
一个表达式的结果
3.1 用户函数
- 代码示例
;不传参函数,cad命令行输入(demo1)运行 (defun demo1 () ;此处可以写语句 ) ;传参函数,cad命令行输入(demo2 3)运行 (defun demo2 (a) ;此处可以写语句 ) ;传参函数,cad命令行输入demo3运行 (defun c:demo3 () ;可以直接调用当前源码文件中其他函数 (demo1) ) ;定义了参数a和局部变量r(作用域仅函数内,用完即释放内存) (defun c:demo4 (a / r) (demo2 3) )
四、语句
4.1 常规语句
4.1.1 赋值语句
- 常规赋值
;赋值,必须以括号括起来每一个语句 (setq a 1) (setq a 1.0) (setq a "1") ;连续赋值 (setq a 1 b 2) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;赋值表,list函数,返回(1 2 0),对每个表元素做类型检测 (setq a (list 1 2 0)) ;赋值表,英文单引号,返回值相同,不对每个表参数做类型检测 (setq a '(1 2 0)) ;获取表元素:(car a)返回1,(cadr a)返回2,(caddr a)返回0 ;删除表首元素: (cdr a)返回(2 0),不修改a元素 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;交互式赋值:getreal、getint、getpoint (setq a (getreal "\n请输入一个实实数:")) (setq distance (getdist '(0 0 0) "两点直接距离为:"))
cad命令行获取变量值:cad命令行输入
!a
,即可返回a的值 - 设置系统变量
(defun C:demo () (print "start testing") ; 获取系统变量,设置系统变量,这里是获取设置对象捕捉 (setq osmode_bak (getvar "osmode")) (setvar "osmode" 0) (print "do sth") ; 还原系统变量,可以注释这一条看效果 (setvar "osmode" osmode_bak) (princ) )
- 字符串语句
; 返回:"abcdef" (strcat "abc" "def")
- 类型转换
;整型转字符串:"3" (itoa 3) ;浮点型转字符串:"3.0000" ;第一位:1、科学计数法 2、小数 5、分数 ;第二位:小数位数 (rtos 3.0 2 4) ;字符串转整形:4 (atoi "4.5") ;字符串转浮点型:4.34567 (atof "4.34567")
4.1.2 命令行输出语句
- 代码示例
;cad命令行输出:不分辨转义字符,先换行再打印,最后加一个空格 ;常用于打印非字符串元素 ;命令: DEMO1 ;"\na" ;"\na" (defun c:demo1 () (print "\na") (print "\na") (setq a "test") ;函数会返回最后一个表达式的返回值, ;此句让函数最后返回空 (princ) ) ;cad命令行输出:分辨转义字符,常用于打印字符串 ;命令: DEMO2 ;a ;a (defun c:demo2 () (princ "\na") (princ "\na") (setq a "test") ;函数会返回最后一个表达式的返回值, ;此句让函数最后返回空 (princ) ) ;cad命令行输出:常用于跟文件打印连用 ;命令: DEMO3 ;"\na""\na" (defun c:demo3 () (prin1 "\na") (prin1 "\na") (setq a "test") ;函数会返回最后一个表达式的返回值, ;此句让函数最后返回空 (princ) )
多语句拼接:
(princ "\na的值是:") (princ a)
4.1.3 运算语句
- 代码示例
;代表1>0,返回T,假的话返回nil ;还有< <= >= > = /= (> 1 0) ;代表1+0,返回1,还有+ - * / (+ 1 0) ;特例,相当于(+ i 1),和(- i 1) (1+ i) (1- i) ;循环中i自加1 (setq i (1+ i))
4.1.4 逻辑语句
- 代码示例
;逻辑与语句 (and (> a b) (< c d)) ;逻辑或语句 (or (> a b) (< c d)) ;否定语句 (not (= a 1))
4.1.5 直接调用cad原生命令
- 代码示例
(defun c:demo4 () ;最后一个""是命令最后输入的enter (command "line" '(0 0) '(100 100) "") ;两点画圆 (command "circle" "2p" '(0 0) '(100 100)) ;屏幕点选画圆 (setq center (getpoint "\n请输入或选择圆心:")) (setq radius (getdist center "\n请输入或选择半径:")) (command "circle" center radius) ;command函数正常执行返回值是nil ;删除最后一个生成的元素 (command "erase" (entlast) "") (princ) )
4.2 流程控制语句
4.2.1 判断语句
- 代码示例
;单语句判断,若第二个语句不写,则默认为nil (if (> a 1) ;常量可直接写 "如果为真,返回这句话" "如果为假,返回这句话" ) (if (> a 1) ;如果真返回第一个表达式,如果假返回第二个 (setq a 1) (setq a 2) ) ;多语句判断 (setq a (getint "请输入一个整型:")) (if (> a 1) (progn (princ "a") (princ "b")) (progn (princ "c") (princ "d")) )
4.2.2 循环语句
- while、repeat语句
;while语句:指定条件 (defun c:demo1 () (setq a 0) (while (< a 500) ;循环打印0~499 (print a) (setq a (1+ a)) ) (princ) ) ;repeat语句:指定次数 (defun c:demo1 () (setq a 0) (repeat 3 ;循环3次 (print a) (setq a (1+ a)) ) (princ) )
- 针对数组遍历函数
;foreach语句:遍历表 (defun c:demo1 () (setq s '(1 2 3)) (foreach temp s (print temp) ) (princ) ) ;mapcar语句:遍历表,并配置遍历函数, ; foreach的升级版,功能相同 (defun c:demo2 () ;匿名函数lambda:将每个元素传入temp,处理后返回 (setq s_recal (mapcar '(lambda (temp) (1+ temp)) '(1 2 3))) (print s_recal) (princ) ) ;mapcar语句:做更复杂的遍历操作 (defun c:demo3 () (setq a (mapcar 'find_ele (entget (car (entsel))))) ;输出((-1 . <图元名: 7ff4650e9180>) nil nil nil nil nil nil 。。。) (print a) (princ) ) (defun find_ele (temp) ;函数返回值会被添加进a中 (if (= -1 (car temp)) temp) ) ;vl-remove-if函数:返回b的值为remove的元素 ; 即返回不满足函数判断式的元素 ;vl-remove-if-not函数:返回b为符合函数判断式的元素 (setq a (list 3 4 5 6 7)) (setq b (vl-remove-if '(lambda (temp) (> temp 5)) a))
4.2.3 条件判断语句
- 代码示例
(defun C:demo () (setq a (getint "输入一个整数:")) (cond ( (= a 1) (alert "输入了1") (alert "结束1") ) ( (= a 2) (alert "输入了2") (alert "结束2") ) (T (alert "输入了其他") (alert "结束其他") ) ) (princ) )
4.2.4 高频应用
- 查找表中元素并替换
(defun c:demo1 () (setq s '((1 2) (3 4) "12" "34")) (setq i 0 new ()) (repeat (length s) (if (= (nth i s) "12") (setq new (append new (list "56"))) (setq new (append new (list (nth i s)))) ) (setq i (1+ i)) ) (print new) (princ) )
- 进阶批量赋值
; 常用于提取文件中数量庞大的点 (defun C:demo () ; 赋值操作:建议使用完重新给他们都赋值nil (setq i 1) (repeat 5 ;read函数:可以将后面的字符串处理成变量名 ;set函数:(set 变量名 变量值),通常跟read函数联合使用 (set (read (strcat "pt" (itoa i))) (getpoint "\n请在屏幕上点选")) (setq i (1+ i)) ) ; 取值操作 (setq i 1) (repeat 5 ;eval函数:执行后面紧跟的函数式, ; (eval 变量名)等同于命令行输入:!变量名 (print (eval (read (strcat "pt" (itoa i))))) (setq i (1+ i)) ) (princ) )
- 输出
命令: DEMO (46577.4 23582.4 0.0) (68048.6 24876.3 0.0) (59119.3 18338.7 0.0) (34171.8 23718.6 0.0) (65322.1 24127.2 0.0) 命令:
五、图元操作
5.1 定义
- 定义:每个可视cad元素均为一个图元,图元之间以链表形式互相连接,可以用
(entsel “提示文字,选填”)
命令选择,返回:(图元名,点选处的坐标) - 示例如下图
5.2 图元选择
- 常用语句
;以下命令在命令栏测试 ;图中点选图形元素 (setq e1 (entsel "请在途中选择图元:\n")) ;选择刚刚点选的下一个元素:因为是链表存储,所以按 ;绘图顺序依次选取下一个 (setq e2 (entnext (car e1))) ;选择第一个图元 (setq e3 (entnext)) ;选择最后一个(还未删除的)元素 (setq e4 (entlast))
命令栏返回:(<图元名:>(鼠标点选图元时的坐标,注意不是图元的夹点))
显示验证:可以在命令行输入move
命令,在选择对象处输入!e2
,图中会虚线显示被选中图元,(type e2)
返回enname
- 命令行获取图元属性列表:
(entget (car (entsel)))
,图中选择图元并返回图元属性列表
5.3 图元属性列表
5.3.1 分部每个函数意义
- 获取图元属性点对列表
;以下命令在命令栏测试 ;图中点选圆这个元素 (setq e1 (entsel "请在图中选择图元")) ;获取图元名 (setq e1_name (car e1)) ;显示图元属性列表:元素为圆
- 获取点对列表中的某一点对表
;获取属性点对列表的所有项,以下是圆的 (setq ent_list (entget e1_name)) ;!ent_list返回:((-1 . <图元名: 7ff425c06280>) (0 . "CIRCLE") ;(330 . <图元名: 7ff425c039f0>) (5 . "2D8") (100 . "AcDbEntity") ;(67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbCircle") ;(10 0.0 0.0 0.0) (40 . 1000.0) (210 0.0 0.0 1.0)) ;获取属性列表的某一项,组码为40,返回:(40 . 1000.0) ;若组码填10,返回:(10 0.0 0.0 0.0) (setq old_r (assoc 40 ent_list))
- 生成点对表(注意跟表list的区别)
;数点对表的构建,下式返回:(40 . 500.0) (setq new_r (cons 40 500.0)) ;坐标点对表的构建,下式返回:(10 1000 1000 0) ;(cons 10 '(1000 1000 0))或(cons 10 (list 1000 1000 0)) ;字符点对表的构建,下式返回:(8 . "图层1") ;(cons 8 "图层1") ;不可用列表生成点对列表 错误 (setq list1 (list (1 . 2) (2 . 3))) 可以 (setq list1 '((1 . 2) (2 . 3)))
- 替换原属性点对列表的一项
;subst函数:用新点对表更新旧点对表,并返回替换后的点对列表 ; 此处用返回值直接重新赋值原属性表变量 (setq ent_list (subst new_r old_r ent_list)) ;如果是随层的、随块的,如颜色线性等,属性列表中是不显示的,需要新增 ;生成(62 . 1),然后打开ent2_list,并将之前点对列表加进并覆盖ent2_list (setq ent2_list (cons (cons 62 1) ent2_list))
- 刷新更新模型区图像
;entmod函数:返回更新后的图元属性列表,entmod更新图元, ; 并将更新后的图元属性列表重新赋值给ent_list (setq ent_list (entmod ent_list))
5.3.2 综合修改并更新图元
- 选择并修改圆颜色
;获取图元属性列表 (setq ent_list (entget (car (entsel)))) ;因为随层,圆颜色点对表不存在,新增 (setq ent_list (entmod (cons (cons 62 3) ent_list))) ;因刚已新增颜色项目,可以直接修改颜色项 (setq ent_list (entmod (subst (cons 62 5) (assoc 62 ent_list) ent_list)))
- 新建圆
;entmake函数:给出最少参数,图元类型,颜色,圆心,半径 ;等同(command "circle" '(1000 0 0) 1) (entmake '((0 . "CIRCLE") (62 . 1) (10 1000.0 0.0 0.0) (40 . 1.0)))