本帖最后由 Gaudi 于 2024-5-8 16:56 编辑
本来想把每一篇涉及的知识点总结下,方便各位大佬翻阅查看。 结果我犯懒了……实在是嫌麻烦。 就做个超链接目录吧……
目录 第三篇 第一部分 新建图层
第三篇 第二部分 读取指定文件夹地址
第三篇 第三部分 读取指定excel表数据
第三篇 第四部分 返回指定文字的坐标和角度、根据坐标和角度插入指定块并移动到指定图层
第三篇 第五部分 修改增强属性块中特定属性标签的属性值
第零篇 前言和叠甲
这是一份记录贴,里面充斥着大量非专业的概念和自己摸索出来的错误信息。 同时也基本上都是重复造轮子,只是在轮子上增加一些自己的贴纸和花纹而已。
甚至不知道发到这里合不合适。如果不合适,烦请版主移动……
那为什么还要买激活码发到论坛里呢。 主要是希望能记录下这份历程,方便自己回看。
然后是希望各种大佬路过的时候帮我解决下问题……
当然,如果能让跟我一样的小白lisp玩家能少走些弯路,能从中有些许收获,那就再好不过了。 是的,虽然这是一个具体的工程案例,但里面的代码思维和函数使用,我个人觉得还是有一定适用性。
我会以个人实际产生的需求出发,记录一步步写出这个lisp程序的历程,中间踩了多少坑、有了多少想法,都会随着逐行代码注释下来。
最终的成果是一系列的LSP文件: 新建图层、获取指定文件夹路径、excel数据读入、查找特定值、属性块插入、属性块数值修改、移动图层,合并而来的标志牌标注和护栏标注。 ——以及踩过无数的坑,和获得无数的思考。
这是一个大工程,希望我不要断更。 如果有哪儿不专业或者写错了,请路过的大佬们直接指出来。
追更的朋友可点只看楼主。
耐心跟着这篇记录一起走,相信你看完了一定会有所收获。
开始!
第一篇 功能拆分和autolisp基础认知
0 起因
团队接了600多公里的安全防护设施项目,通过外业数据excel表成套产出工程量表格的工作早已完成,这次项目的时间卡点就在平面图布设上。 通过外业调查而来的桩号、类别(标志牌、砼护栏、波形梁护栏)、方向、处治方式,按一定的规则,将特定的块插入到具体的位置上,还要根据左右方向和主线角度确定块的选装方向,同时要根据不同的处治方式和类别分门别类放置到不同的图层中。
工程量巨大,按以往的经验,起码接近200个工时才能把这一个步骤搞定,还不一定保证完全正确。
如果涉及到删减、增改,那就是欲哭无泪。
1 开始的老办法
初步解决这个问题其实很早,通过CAD自带 dataextraction 命令,提取所有桩号点的坐标和内容,再通过 excel 转换命令,形成 -inser t和 -attedit 命令组,再复制到CAD命令行里执行。 这种操作还是很简单的。
可惜太复杂了点,只适合路线数量少、路线里程长的情况。 所以刚弄出适用成功就被封存了。
转头看向lisp。 工作七八年了,一直没怎么接触,这次不得不硬着头皮啃下来。
2 功能拆分
按我朴素的想法,计算机是很笨的。它只接受一句一句最简单、婴儿式的命令。 所以第一步就是步骤拆分,拆分到你觉得不能再拆分为止——这也是为什么最终产生了若干个子功能LSP程序。 后来我发现这个习惯好像挺不错,不同的功能单独测试,单独成块。
A 桩号标注(选择主线、得出实际长度、确定终点桩号、分隔成一米的间距、找到标注点、标注桩号) B 新建图层(根据参数确定图层名称、根据图层名称确定现型线宽颜色) C 获取指定文件夹路径(打开包含块的文件夹、获得这个文件夹的路径) D 获取外业数据(打开excel、找到指定工作簿、找到指定工作表、找到指定数据范围、返回数据到CAD) E 找到块插入位置(找到桩号位置、返回桩号和旋转角度) F 插入属性块(根据块名找到块、插入块) G 移动块(将插入的块移动到指定图层) H 修改块属性(根据外业找到特定属性标签、修改属性)
八个子程序!最后还要合并成一个lisp程序。 没办法,开搞吧。
3 初步lisp了解(极具个人向)
不掉书袋去分析这个分析那个了。
核心就是用lisp执行cad命令,有三个方向: 一个是 command+CAD 命令,然后根据参数一步步填,这个本质上是模拟输入。 一个是调用lisp里自带的函数,输入特定参数。 一个是 vla 系列,这个有点绕,大致上相当于把CAD这个小圈子里的东西,转变为微软这个大佬搞的一个平台里都认识的东西,这个平台叫 com。转变后,再用这平台的通用命令去操作。
第一个最简单,能用这个解决就不用想着别的了。但是最简单的一般可操作性就最少,这次就碰见一个案例。 第二个和第三个都比较常见,理解难度第三个稍微复杂一点。 为什么要用第三个办法,有时候是因为必须,比如各软件之间数据的连接;有些时候是因为这种办法相比传统办法更加简单清晰;有些时候是传统办法不能达成需求。
4 lisp语言结构
不得不说,lisp括号匹配真麻烦啊…… 每一句都要有括号匹配,一般提示“输入的列表有缺陷”就是这个错误。 这里要说下,为什么会提示“列表”而不是代码呢? 因为lisp语言就是一个列表语言,每一对括号就像是表里内容,然后一句一句由内往外或者由上往下运行。
- (defun c:Program (AAA \BBB)
- (XXX)
- )
Defun是固定开头。 “c:”表示可以使用函数名通过命令行去调用。 “Program”是函数名,可以在内部调用。 “AAA”是全局变量,意思可以传递给其他函数。 “BBB”是局部变量,只在自身函数内部使用。(我一般都懒得定义)
没了。 很简单不是吗。
5 基本函数 -command:调用CAD命令
command 的用法,无脑得很,你就打这个命令,然后看命令行需要什么就写什么。
- (command "line" Point1 Point2 "")
只要把两个点的坐标传递进去,就能直接画线。
6 基本函数-Setq:定义
有时候你可能会看到 set,好像也有这个功能。 不用管它,用 setq。 - (setq a 1)
把1的数值定义到a. - (setq a b)
把b的数值定义为a.
这这种都是基础,比较常用的下面几种: - (setq folderPath (GetFolderAddress))
运用上述所学! “因为lisp语言就是一个列表语言,每一对括号就像是表里内容,然后一句一句由内往外或者由上往下运行。” ““Program”是函数名,可以在内部调用。” 那么从最右的 ( 开始及运行,先是 GetFolderAddress 调用这个自定义函数,把调用这个函数的结果,通过 setq 定义到 folderPath 变量。
来个复杂点的: - (setq textPosition2 (polar textPosition (* textAngle (/ PI 180)) 20))
从最右的(开始运行。 / PI 180,加减乘除就不说了,看一眼函数定义就知道。 (polar …… …… ……),这就是 polar 极坐标函数调用格式,套进去就行。 (setq textPosition2 (……)),把计算结果定位到 textPosition2 里去。
7 基本函数-if:条件判断
If语句的通用格式: - (if XXX
- (progn
- (XXX)
- )
- (progn
- (xxx)
- )
- )
If 后面跟判定语句,然后先真后假。 如果有很多语句需要判定后一起执行,就加个 progn 框起来。
判定语句可以和 not、and、or 连接起来用,这个看名词也知道是怎么回事了。
8 结束
到这里,就结束了。 这个快结束了吗? 是的,这么快就结束了。
只要掌握了基本函数结构、command-CAD命令调用、setq-参数定义、if-条件判断,很多功能就可以写了。
比如说,上述子程序G移动图层: - (defun MoveBlock2Layer (treatMent cateGory)
- (setq layername (strcat treatMent cateGory))
- (command "change" "l" "" "p" "la" layername "")
- )
这里面多了一个函数 strcat,字符串连接成一个新的字符串。
比如说,上述子程序F插入属性块: - (defun InsertBlock (folderPath blockName textPosition textAngle)
- (setq blkDef (strcat folderPath "\\" blockName ".dwg"))
- (if (findfile blkDef)
- (progn
- (setq blkDef (strcat "*" blkDef))
- (command "_insert" blkDef textPosition "1" textAngle)
- )
- (progn
- (princ (strcat blkDef "\n该地址没有找到相应块。"))
- (exit)
- )
- )
- )
这里面多一个 finfile,就是判定这个块文件有没有,有就真,没有就假。 还有 princ,把字符串或者函数的值在命令行里显示出来。 Exit,停止。
比如加载线型: - (defun loadlinetypes ()
- (if (not (tblsearch "LTYPE" "TRACKS"))
- (command "_.linetype" "Load" "TRACKS" (strcat "acadiso" ".lin") "")
- )
- (if (not (tblsearch "LTYPE" "DASHDOT"))
- (command "_.linetype" "Load" "DASHDOT" (strcat "acadiso" ".lin") "")
- )
- (if (not (tblsearch "LTYPE" "ZIGZAG"))
- (command "_.linetype" "Load" "ZIGZAG" (strcat "acadiso" ".lin") "")
- )
- )
这里面多一个 tblsearch,tbl是table的简写,图层搜索嘛,有就真,没有就假。
所以不要畏难,非常简单。
你不能用lisp解决所有操作,可以先解决一部分操作嘛!
能偷懒就不要加班。
中午吃饭了,休息下。
|