美国Autodesk公司开发的AutoCAD系统自1982年推出以来,以其使用方便、功能强大和系统开放性一直独领风骚。成为各工程领域首选的CAD系统。
水利水电工程领域利用AutoCAD平台进行二次开发也取得了一系列成果,如90年代以来陆续开发的水电站地面厂房CAD系统、重力坝CAD系统、隧洞CAD系统、水机油汽水CAD系统、地质柱状图CAD等均取得了较好的应用效果。但水电工程设计的复杂性决定了任何现成的CAD软件都有其局限性,设计过程中许多问题还只能用原始的方法解决。本文通过几个实例对AutoCAD二次开发常用的Lisp语言在水电工程设计中的应用进行了初步探讨,希望能够起到抛砖引玉的作用。
VisualLisp语言是AutoCADR14版本以后提供的全新的开发环境,是嵌于AutoCAD内部,将Lisp语言与AutoCAD相结合的产物,是一种智能型语言。利用AutoLisp可以灵活方便地增加AutoCAD新命令,几乎无限地扩展AutoCAD新功能,
2 应用实例
2 .1 坐标画线
利用已知坐标点画线是设计工作中经常遇到的问题,如河道、堤防等实测断面、水位流量关系曲线、堰面曲线等数据的处理,均可归结为坐标画线问题。对于堰面曲线等有函数方程的曲线可以利用EXCEL按照期望的步长自动生成一系列坐标点。对于测量常用的起点距-高程形式的数据,也可以利用EXCEL转化成坐标点形式。
(1)利用脚本文件(.SCR)
利用任何文本编辑器如Note、Uedit、Word、Excel等建立纯文本文件EX1.SCR,注意文本文件后缀必须为.SCR,坐标之间用半角逗号分开,文件中不允许出现空格,文件最后一行必须为空回车。文件建立时,可以直接把 EXCEL或其他文件中的坐标表利用拷贝、粘贴功能加入脚本文件中。
Pline
345.66,238.65
213.45,124.56
128.44,235.66
文件保存后,执行AutoCAD中“工具”下的“运行脚本”,在显示的窗口中查找并选中EX1.SCR,屏幕上会立即显示所绘线条。
(2)利用LSP程序
建立坐标表文件EX2.DAT,后缀任意,可以依次输入多段曲线,中间用曲线名称分开,程序自动绘制多条曲线并可标注坐标表。
“曲线1”
213.45,124.56
128.44,235.66
345.66,231.78
“曲线2”
433.34,567.23
434.12,464.12
利用AutoCAD中“工具”菜单下的“VisulLisp编辑器”建立DRLINE.LSP文件如下
(defun C:drline()
(if fn
(setq fn (getfiled "坐标点文件名" fn "" 2))
(setq fn (getfiled "坐标点文件名" "" "" 2))
)
(setq f (open fn "r"))
(setq p0 (getpoint "/n画线起点:"))
(setq bz 0 mm 1)
(command "pline")
(while (/= bz 1)
(setq md (read-line f))
(if (/= md nil)
(setq zbb (read md))
(setq bz 1)
)
(setq dx (car zbb) dy (cadr zbb))
(setq p1 (list (+ dx (car p0))
(+ dy (cadr p0)))
)
(command p1)
(setq mm (1+ mm))
)
(command "")
(close f)
)
文件存盘后,加载运行,相当于新增加了坐标画线命令DRLINE,按提示选中存放坐标表的文件即可实现自动绘制曲线。
2 .2 地形切剖面
水电工程设计中经常遇到在地形图上切剖面的问题,借助Visual Lisp可以实现快速切剖面。
(1) 初始地形图处理
把带z坐标的地形平面图进行变换,变换后z坐标值成为层名,为加快切剖面运行速度,把“LWPOLYLINE”和”SPLINE”均转化为”LINE“线,程序如下
(defun c:pltol()
;LWPOLYLINE转化为LINE
(setq n 0)
(setq e (ssget"X" (list (cons 0 "LWPOLYLINE"))))
(setq sh (sslength e))
(if e
(while (< n sh)
(setq e1 (ssname e n))
(command "pedit" e1 "d" "")
(setq x (entget e1))
(setq ngc (atof (setq la (fld 8 x))))
(command "explode" e1)
(setq n (+ n 1))
) ) )
(defun fld (num lst)
(cdr (assoc num lst))
)
(defun c:spltol ()
;SPLINE转化为LINE
(setq n 0)
(setq e (ssget "X" (list (cons 0 "SPLINE"))))
(setq sh (sslength e))
(if e
(while (< n sh)
(setq x (entget (setq e1 (ssname e n))))
(setq nla (itoa (fix (caddr (fld 10 x)))))
(if (= (fld 0 x) "SPLINE")
(progn
(command "layer" "n" nla "c"
"6" nla "s" nla "")
(command"line")
(setq nm (length x)
dzs (fld 73 x) dzs1 (fld 74 x))
(while (> nm 5)
(if (= (car (nth nm x)) 10)
(progn
(setq b1 (nth nm x))
(setq x1 (cadr b1))
(setq y1 (caddr b1))
(setq z1 (cadddr b1))
(setq glb (list x1 y1))
(command glb)
) )
(setq nm (- nm 1))
)))
(command "")
(setq n (+ n 1))
)))
(2)切剖面
输入剖面编号,在平面地形图上指定两点确定剖面剖切线位置,指定剖面图起点,利用AutoCAD的inters函数搜索剖切线与地形图的全部交点,自动计算交点坐标,计算交点与剖面位置起点的距离,按各交点高程和与起点的距离形成剖面图各点坐标,即可用本文实例1坐标画线生成地形图的剖面。
(defun dxtent1 ()
(setq n 0 xdzb nil)
(setq xds 0)
(setq sh (sslength e1))
(while (< n sh)
(setq x (entget (ssname e1 n)))
(if (= (fld 0 x) "LINE")
(progn
(setq dxtgcgc (fld 8 x))
(setq dxtgcgc (atoi dxtgcgc))
(if (> dxtgcgc 10)
(progn
(setq pst (fld 10 x))
(setq pet (fld 11 x))
(setq zb (list gc
(list (car pst) (cadr pst))
(list (car pet) (cadr pet))
))
(setq xdzb (cons zb xdzb))
(setq xds (+ xds 1))
))))
(setq n (+ n 1))
))
(defun c:dxtsec ()
(setq pmh (+ pmh 1))
(setq pmh (getstring "/n 剖面号" ))
(setq pt1 (getpoint "/n 剖切位置起点:"))
(setq pt2 (getpoint pt1 "/n 剖切位置终点:"))
(setq pt3 (getpoint "/n 剖面图布置:"))
(setq p01 pt3)
(setq e1 (ssget "F" (list pt1 pt2)));利用AutoCAD的目标选择“F”方式选取与剖切线相交的地形线。
(dxtent);获取与剖切线相交地形线的坐标
(setq mxgc -100)
(setq mngc 10000)
(setq m 0 pmp nil)
(setq n xds i 0)
(while (< i n)
(setq crosp
(inters pt1 pt2 (nth 1 (nth i xdzb)) (nth 2 (nth i xdzb)) 1)
);求剖切线与地形线的交点
(if (/= crosp nil)
(progn
(setq dxtgcgc (nth 0 (nth i xdzb)))
(setq mxgc (max mxgc dxtgcgc))
(setq mngc (min mngc dxtgcgc))
(setq dst (distance pt1 crosp));剖切线起点与交点的距离
(setq dst (* (/ blcz dxthtbl) dst))
(setq pmp (cons (list m dst dxtgcgc) pmp))
(setq m (+ m 1))
))
(setq i (+ i 1))
))
2 .3 沿曲线标注
在设计中会遇到沿给定曲线进行标注问题,如平面布置图中的开挖线符号沿开挖轮廓的标注,剖面图中岩石符号沿轮廓线标注、点筋标注、沿任意曲线进行汉字标注等。此类问题主要应用AutoCAD的Measure或pide命令来解决。两个命令的主要差别是前者按指定的长度在曲线上标注,后者按给定的分段数等分曲线并在等分点处进行标注。要标注的轮廓曲线最好用pline线,要标注的符号预先做成图块,图块采用单位块,执行measure或pide命令,选取要标注的曲线,指定标注符号,分段长度或分段数即可完成标注,当发现标注的符号太密或太疏时,可以执行erase命令选择P进行删除,比例不合适或符号方向不正确,可以利用特性编辑器,选中所有标注符号,对标注符号的比例和旋转角度进行调整,直到满意为止。对于更高级的应用,可以编制LSP程序,实现符号和文字沿任意曲线标注。
2 .4 表格生成
AutoCAD本身没有表格处理功能,设计图纸中工程量表、钢筋表等涉及到表格生成的问题可以采用以下方法处理:
(1)直接把Word或Excel文件中的表格直接粘贴到CAD图形中,修改时只要双击图中的表格即可进入Word或Excel中进行编辑修改,修改完成后退出即可返回到AutoCAD中继续进行设计,该法优点是方便,快捷,易于掌握,可以充分利用Excel的强大计算功能。缺点是表格在AutoCAD中并不是一个普通图元,无法利用CAD功能对表格的字高、颜色和线宽进行编辑。
(2)编制LSP程序,依次输入表格标题、表格行数、表格列数、表格行高和列宽以及表格插入点等参数,可以自动生成表格,表格中已经按仿Excel形式填入了文字,可以用字处理软件对表格中文字进行编辑修改。
(defun C:mtab()
(setq tb1 nil tb2 nil tb3 nil)
(setq rows (getint "表格行数"))
(setq cols (getint "表格列数"))
(setq rowh (getreal "行高"))
(setq colw (getreal "列宽"))
(setq p1 (getpoint "/n表格左上角点位置:"))
(command "pline" p1 "w" "0.5" "0.5"
(setq p2 (list (+ (car p1) (* cols colw)) (cadr p1)))
(setq p4 (list (car p2) (- (cadr p2) (* rows rowh))))
(setq p3 (list (car p1) (- (cadr p2) (* rows rowh))))
"C" )
(setq n 1)
(while (< n rows);绘水平线表格
(command "pline" (list (car p1) (- (cadr p1) (* n rowh))) "w" "0" "0"
(list (car p2) (- (cadr p2) (* rowh n))) "")
(setq n (+ n 1))
)
(setq n 1)
(while (< n cols) ;绘垂直表格线
(command "pline" (list (+ (car p1) (* n colw)) (cadr p1)) "w" "0" "0" (list (+ (car p1) (* n colw)) (cadr p3))
"")
(setq n (+ n 1))
)
(command "text" "m" (list (+ (car p1) (* 0.5 cols colw))
(+ (cadr p1) 5)) "3" "0" "TITLE" )
(setq n 0)
(while (< n rows)
(setq m 0)
(while (< m cols)
(cond
((< m 26) (setq bzstr (chr (+ 65 m))))
((>= m 26) (setq bzstr (strcat (chr (+ 64 (/ m 26))) (chr (+ 65 (- m (* 26 (/ m 26))))))))
)
(command "text" "m" (list (+ (car p1) (* 0.5 colw) (* m colw));表格内容标注
(- (cadr p1) (* 0.5 rowh) (* n rowh)))
(getvar"TEXTSIZE") "0" (strcat bzstr (itoa (+ n 1))))
(setq m (+ m 1))
)
(setq n (+ n 1))
))
2 .6 高程小数位数处理
尺寸标注小数位数很容易调整,但诸如高程、表格中数字要调整则很困难,借助LSP程序的调整很方便,只要选取需要调整的数字,根据提示输入需要保留的小数位数,则程序自动对所有选种数字进行修改。
(defun entsgc()
(setq n 0)
(setq sh (sslength e1))
(while (< n sh) (setq x (entget (ssname e1 n)))
(if (= (fld 0 x) "TEXT")
(progn
(setq agc (fld 1 x))
(setq c (substr agc 1 1))
(if (or (= c "+") (= c "-") (and (>= c "0") (<= c "9")))
(progn
(if (or (= c "+") (= c "-"))
(setq bgc (substr agc 2))
(setq bgc agc)
)
(setq cgc (atof bgc))
(setq zh (rtos cgc 2 gcws))
(if (or (= c "+") (= c "-"))
(setq zh (strcat c zh)))
(setq x (subst (cons 1 zh) (assoc 1 x) x))
(entmod x)
)
))
))
(setq n (+ n 1)))
)
(defun c:yxws()
(setq e1 (ssget))
(setvar "dimzin" 0)
(setq gcws (getint "保留小数位数:"))
(if e1 (entsgc) (print "/n not found"))
(setq x nil)
)
2 .7 应用软件前、后处理
由于软件升级滞后,一些常用软件后处理功能很弱或没有,可以利用LSP程序结合AutoCAD增加或简化前后处理功能。下面结合平面渗流分析程序STSE软件对其前、后处理功能的实现进行介绍:
(1)前处理
STSE为平面渗流有限元程序,单元划分和单元、节点编号工作量最大,可以借助其它通用有限元软件的前处理功能如Ansis、Algor、SAP84等进行初步处理,生成单元、节点编号和节点坐标,而后按照STSE数据文件的格式要求对数据文件进行编辑。
(2)后处理
后处理成果主要为:单元网格图,浸润线和等势线。单元网格图中有节点和单元编号,不同渗透系数的单元采用不同的颜色,以便根据网格图直观地判断数据文件中几何参数和材料特性的正误;
首先分析STSE的输出结果文件的格式,搜索并筛选其中主要参数如单元总数、节点总数和材料总数,把节点坐标和单元信息分别存储,通过对单元循环生成单元网格图。
(defun c:seepmesh()
(if fn
(setq fn (getfiled "渗流结果文件名" fn "" 2))
(setq fn (getfiled "渗流结果文件名" "" "" 2)))
(setq f (open fn "r"))
(setq md (read-line f))
(while (/= (substr md 25 8) "单元总数")
(setq md (read-line f))
);定位单元总数
(setq dyzs (atoi (substr md 58 5)));读单元总数
(setq md (read-line f))
(setq jdzs (atoi (substr md 58 5)));读节点总数
(setq md (read-line f))
(setq clh (atoi (substr md 58 5)));读材料总数
(setq m 0)
(repeat clh
(setq m (+ 1 m))
(setq tcm (strcat "zclh" (itoa m)))
(command "layer" "m" tcm "c" (itoa m) tcm "")
);按材料种类生成图层名称
(setq m 0 n 0)
(repeat dyzs;对单元循环,dycfb中存放单元信息
(setq m (+ m 1))
(setq clh (nth 0 (nth m dycfb)))
(setq jdh1 (nth 1 (nth m dycfb)))
(setq jdh2 (nth 2 (nth m dycfb)))
(setq jdh3 (nth 3 (nth m dycfb)))
(setq jdh4 (nth 4 (nth m dycfb)))
(command "layer" "s" (strcat "zclh" (itoa clh)) "")
(command "pline";绘制单元网格
(nth jdh1 jdzbb)
(nth jdh2 jdzbb)
(nth jdh3 jdzbb)
(nth jdh4 jdzbb) "c")
(setq bzdzb (mapcar + (nth jdh1 jdzbb) (nth jdh2 jdzbb)
(nth jdh3 jdzbb) (nth jdh4 jdzbb)))
(setq bzdzb (list (/ (car bzdzb) 4.0) (/ (cadr bzdzb) 4.0)))
(command "text" "m" bzdzb "0.5" "0" (itoa m))
;标注单元号
(setq m 0)
(repeat jdzs
(setq m (+ m 1))
(setq bzdzb (nth m jdzbb))
(setq bzdzb (list (+ (car bzdzb) 0.0) (+ (cadr bzdzb) 0.0)))
(command "text" "m" bzdzb "0.5" "0" (itoa m))
));标注节点号
(close f)
)
限于篇幅,等势线和浸润线生成程序不再赘述。同样,对工程设计中遇到的其它软件如:STAB边坡稳定分析、SAP84的输出文件均可进行类似后处理工作。
3 结语
AutoCAD软件应用已经在设计单位普及,VisualLisp的出现对于提高Lisp语言的编程效率和AutoCAD应用水平具有重要意义。本文涉及的几个实例已经在实际工作中发挥很大作用,充分说明在工程设计当中结合本专业要求开发一些简单实用的Lisp小程序可以有效减轻设计人员的劳动强度,使AutoCAD不仅仅是绘图工具,而真正成为设计人员得心应手的高效设计平台。