AutoLISP语言在地下管线测量中的应用
2014-06-28陈培龙
陈培龙
(漳州市测绘设计研究院,福建 漳州 363000)
1 引 言
随着国民经济的发展,我国的城市建设也取得了巨大的成就。近年来城市测量工作在城市发展中的作用越来越突出,而城市地下管线测量作为城市测量工作的重要组成部分,越来越受到相关部门的重视。城市建设的飞速发展,原有城市地下管线资料欠缺的矛盾越来越突出。因此查明地下管线,并确定其分布、埋深及走向等管点特征信息,建立一个有效的、简洁的管线信息测量录入系统,就显得更加迫切[1]。笔者所在单位进行的管线测量成果一般以Excel 电子表格的形式输出,而日常测量成图又是在AutoCAD 平台下,故笔者利用AutoLISP 编制程序实现AutoCAD 到Excel 的管线点、线表自动输出,从而提高工作效率。
AutoLISP 是内含于AutoCAD 软件中的开发语言,是强化AutoCAD 最好、最直接的程序语言。它最大的特点就是不挑剔编辑环境,几乎在所有的文本编辑器中都可以编写,而且不需要特殊的编译过程。它的语法结构简单易懂,变量定义方便、简洁非常富有弹性。Dcl 是内嵌于AutoCAD 平台的一款对话框语言,该语言和LISP 一样,语法结构简单,不需经过编译,可以在AutoCAD 平台下直接调用[2]。使用LISP+Dcl 能够轻松实现基于AutoCAD 平台的交互输入与输出,功能强大、通俗易用。本系统主要利用AutoCAD 图元可以扩展数据的功能,对管点图块的AutoCAD 属性进行扩展,从而实现管线点、线表自动输出[3]。
2 工作流程
管线测量一般先外业采集管点的坐标及高程信息,然后再对各个管点的特征数据进行采集,该系统主要模拟外业生产流程,根据外业采集的各特征点信息的流程进行录入,通过管线的流向方向,实现管线点、线表从CAD 到Excel 的输出[4]。图1 为地下管线探测工作流程。
图1 地下管线探测工作流程图
3 程序的功能设计
3.1 程序扩展数据结构及Dcl 主键定义
AutoCAD 扩展数据是软件自带的一种扩展方式,其主要结构方式为:(-3(应用名(1000 .文本型属性)(1040.浮点型属性)(1070 .整数型属性))),应用名可以通过“Regapp”函数直接注册,如果注册成功,该应用名会被加入到Appid 符号表中,该表保留了该图形中所有使用扩展数据的应用名[5]。对话框是现今最流行的人机互动界面,在早期的AutoCAD 版本中已经使用,对话框的描述定义在一纯文本文档(后缀名为.dcl)内,无须特别的开发环境,称之为Dcl 语言。在AutoLISP 中内嵌可以直接控制Dcl 对话框的函数,对话框中的每一个对象均有一个唯一的标示符即Dcl 主键名称,通过主键名称,就可以准确的控制对话框的各个部件。对于扩展数据结构及主键的定义如表1 所示。
扩展数据结构及Dcl 主键一览表 表1
3.2 自动展绘管点图块
管线外业采集一般使用全站仪或者GPS 进行采集,采集数据包含测点点名,编码,北坐标X,东坐标Y,高程值H。外业采集的同时需要根据管井的井盖等信息判断出管井的类型,例如污水、雨水、电力、电信、燃气等,然后再对管井进行探测以便采集管点的属性信息如管径、埋深、井深、电缆根数、电缆孔数等[6],依据这些采集的数据,通过使用自动展绘模块快速成图。对于使用该模块,首先每一种管点类型都先约定一个字母代码,如污水管点为W,雨水管点为Y,电力管点为L 等。在内业处理时首先编辑对照文件,文件为文本格式,当文本中出现管点字母代码时,表示该代码后的所有测点点名都是该类型管点,每一行表示一个点名,直到出现其他管点字母代码。
例如:Y
表示点名为100、101 的测点为雨水管点,103、104为污水管点。完成点、线表对照文件编辑后,就可以通过自动展绘管点图块程序,完成管点图块的CAD 成图,同时录入该点的高程值和外业点名。模块界面如图2 所示:
图2 自动画管线的界面
管点展绘后效果如图3 所示:
图3 管点展绘效果图
3.3 管线流向与箭头的绘制
完成管点图块绘制后,需要根据管线实地的连接方向进行连线。AutoCAD 的二维多段线会根据每个端点绘制的顺序形成一个方向,在管点流向绘制时,需保证管点流向的方向与二维多段线的方向保持一致,例如:雨水管线从上游往下游方向绘制,并保证二维多段线每个端点均与管点图块的中心点一致,这样就在绘制流向的同时也就完成了原来互相独立的管点之间拓扑关系的连接。
如果管线的类型是雨水或者污水,那么在完成流向绘制后,还需要在每两个管点之间绘制一个表示流向的箭头。为了保证箭头的一致性和美观性,程序还提供了自动画流向箭头功能,同时约定在两个管点距离大于等于5 m的情况下,箭头长度为1.6,距离小于5 m时,箭头长度缩小为0.6,并保证箭头的顶端位于两管点流向线的中点上,与流向线两侧的夹角均为20°。由于AutoCAD 二维多段线的方向没有直观地显示,故在实际操作中会出现二维多段线的方向与流向的方向相反的情况,为了防止这种情况的出现,在流向箭头绘制程序运行的最后会在命令行提示用户判断绘制箭头的方向是否正确,若用户选择为否(N),则程序会对该流向线进行反向处理,并重新绘制正确的箭头。同时还提供SCJT(删除箭头)命令,可以删除最后绘制的一组箭头,最大限度减少误操作带来的重复劳动。
3.4 管点的快速编号
管点在图形中主要靠管点的编号来识别,因此管点编号的条理性及准确性就显得特别重要。在将管线数据以Excel 表格方式输出后,如何快速将文本数据与AutoCAD 图形联系起来,跟管点编号的方式有很大的关系。为了能更快速、准确、对管点进行编号,程序提供了自动编号模块。运行命令时,首先提示用户选择需要编号的流向线,然后根据用户输入的起始编号,程序会按照流向线方向对线上每个管点进行递增编号。例如:用户输入雨水管点起始编号为Y10D100,程序会对接下去的管点编号为Y10D101、Y10D102……,如图4 所示。
图4 自动画流向箭头效果图
3.5 管点属性录入
完成上述工作后,就需要对外业采集的管点属性信息进行录入。管点的属性录入界面如图5 所示。一般管线测量只有电力和电信需要录入共有孔数、已用孔数、电缆根数这三个属性信息,在程序的运行中,会根据管点的图块名称自动判断出管线类型,如果是电力或电信,则共有孔数、已用孔数、电缆根数三项可以录入信息;如果是雨水或者污水等其他类别的管线则录入框会以灰色不可编辑框的形式出现。预留扩展在程序执行中会以不可编辑框的形式出现,预留扩展是为预防后期管线录入属性增多而准备的,需要使用时必须修改后台程序后才能录入信息,应用本文所提的方法,可以根据需要任意扩展。
图5 管点属性信息录入界面
3.6 点、线表的输出及查错
完成所有的属性录入工作后,就可以输出点线表了。程序约定输入的点、线表自动存放于当前活动图形的同级目录下,并命名为输出点表.csv 和输出线表.csv。用户可以连续选择需要输出的流向线,右键结束选择后,程序将根据选择的流向线,自动输出该线上所有管点的属性信息[7]。
当输出的管线类型为雨水或者污水时,程序会对各点井底高程就行复查,当管点的井底高程大于上一管点井底高程的数值超过某一阈值时(默认设置设为10 cm),会在该行线表的备注栏标注“流不出”,提示用户进行人工再确认,防止出现粗差。由于在连线时已经将流向与二维多段线的方向保持一致,故每次雨、污的流向均为正向。输出效果如图6 所示:
图6 线表输出效果图
4 程序部分源代码
4.1 自动画流向箭头模块部分代码
(setq ssjiantou(ssadd));创建一个集合,将所有箭头放在这个集合内
(setq a(car(entsel)));选择需要画箭头的流向线
(setq leixing(cdr(assoc 0(entget a))));判断对象是否为多段线
(if(=leixing "POLYLINE")(progn
(setq tuceng(cdr(assoc 8(entget a))));判断所在图层
(panduan);判断模块,如果不是雨水或者污水,则程序不再执行
(setq en(entnext a));读取下一图元,用于接下去获取多段线端点坐标
(setq ed(assoc 10(entget en)))
(setq xs(cadr ed));分离出X 值(setq ys(caddr ed));分离出Y 值
(setq pts(list xs ys));构造起始点坐标(setq en(entnext en))
(setq long 1.6);设定每个箭头长度为1.6
(while(/=over "SEQEND")
(setq ed(assoc 10(entget en)))
(setq x(cadr ed));分离出X 值(setq y(caddr ed));分离出Y 值
(setq xzz x)(setq yzz y)(setq pt(list x y));构造点坐标
(setq x(/(+ x xs)2))(setq y(/(+ y ys)2))
(setq ptmid(list x y));构造中点坐标
(if(<(distance pt pts)5)(setq long 0.6));根据端点距离调整箭头长度为0.6
(setq ptmidon(polar ptmid(+(angle pts ptmid)2.792)long));箭头第一个点
(setq ptmiddown(polar ptmid(+(angle pts ptmid)3.4906)long));第二个点
(command "layer" "s" tuceng "");设置流向线所在图层为当前图层
(setvar "thickness" 5441200);设置箭头厚度值
(command "pline" ptmidon ptmid ptmiddown "");绘制箭头
(ssadd(entlast)ssjiantou);将绘制的箭头加入选择集ssjiantou
(setq long 1.6)(setq xs xzz)(setq ys yzz)(setq pts(list xs ys))
(setq en(entnext en));访问下一个子图元,继续绘制箭头
(setq over(cdr(assoc 0(entget en)))));判断子图元是否结束
(initget 0 "Yes No")
(setq keyw(getkword " 流向方向是否正确[是(Y)/否(N)]:")));用户确定方向
(alert "您选择的不是多段线");如果选择的不是多段线则提醒
)
(if(=keyw "No")(chongxinhua));如果用户选择流向方向为不正确,则反向重画
4.2 快速编号模块部分代码
(regapp "gxbh");将gxbh 注册到Appid 符号表中
(if name(progn
(setq arealist(list-3(list "gxbh"(cons 1000 bianh))));构建扩展组
(setq endata(entget name '("gxbh")));检查原图块是否已经编号
(if(=(cdr(assoc 1000(cdr(cadr(assoc-3 endata)))))"")
(progn
(setq oldlist(assoc-3 endata));获取原图元已有的扩展属性
(setq endata(subst arealist oldlist endata));用新的属性替换旧属性
(entmod endata);更新图元
(command "text" pt2 "1.5" "0" bianh);在图上绘制管点编号
(setq num(1+(atoi num)))
(cond
((<num 10)(setq num(strcat "00"(itoa num))));如果编号编号是1,就改为001
((<num 100)(setq num(strcat "0"(itoa num))));如果编号是10 则改为010
((>=num 100)(setq num(itoa num))));如果编号大于100 则不做处理
(setq bianh(strcat zubie num)))
(if(not(assoc-3 endata))(prong
(setq endata(append endata(list arealist)));如果原图元没有编号,则增加新编号
(entmod endata);更新图元
(command "text" pt2 "1.5" "0" bianh)
(setq num(1+(atoi num)))
(cond
((<num 10)(setq num(strcat "00"(itoa num))))
((<num 100)(setq num(strcat "0"(itoa num))))
((>=num 100)(setq num(itoa num))))
(setq bianh(strcat zubie num))))))))
4.3 输出点、线表模块部分代码
(while(<=(+ 1 i)(sslength sszhaodao));遍历流向线上的管点组成的选择集
(if(setq en(ssname sszhaodao i))(progn(setq edsdb(assoc 10(entget en)))
(setq x(rtos(-(+ xyd(/(Caddr edsdb)2))50)2 3));获取图块的北坐标X
(setq y(rtos(-(+ yyd(/(Cadr edsdb)2))50)2 3));获取图块的东坐标Y
(setq km(strcase(cdr(assoc 2(entget en)))));获取图块名称
(if(setq endatabh(entget en '("gxbh")))
(progn(setq endatabhsd(cdr(Cadr(assoc-3 endatabh))))
(if(assoc 1000 endatabhsd)(setq bgdbh(cdr(assoc 1000 endatabhsd))));获取管点编号
(if(assoc 1040 endatabhsd)(setq bgdms(cdr(assoc 1040 endatabhsd))));获取管点名称
(if(assoc 1070 endatabhsd)(setq bgyks(cdr(assoc 1070 endatabhsd))))));获取共有孔数
(if(setq endatakz(entget en '("gxkz")))(progn(setq endatakzsd(cdr(Cadr(assoc-3 endatakz))))
(if(assoc 1000 endatakzsd)(setq bgdgj(cdr(assoc 1000 endatakzsd))));获取上点管径
(if(assoc 1040 endatakzsd)(setq bdmgc(cdr(assoc 1040 endatakzsd))));获取地面高程
(if(assoc 1070 endatakzsd)(setq byyks(cdr(assoc 1070 endatakzsd))))));获取已用孔数…………
完成各变量的获取后则输出点、线表:
(if(and(=tuceng "J")(=km "GC041"))
(setq fushuwu "篦子")(setq fushuwu "检修井"))
(if(=km "GC133")(setq fushuwu "消火栓"))
(if(=km "GC134")(setq fushuwu "阀门"))
(if(=km "GC170")(setq fushuwu "化粪池"));根据图块名称判断出对应的附属物,然后开始输出点表
(princ bwydh f1);输出外业点号(princ "," f1);输出逗号(princ bgdbh f1);输出管点编号(princ "," f1)(princ leixingdb f1);输出管线类型(princ "," f1)
(princ x f1);输出北坐标X(princ "," f1)
(princ y f1);输出东坐标Y(princ "," f1);
(princ bdmgc f1);输出地面高程(princ "," f1)
(if bgdjs(princ bgdjs f1)(princ bgdms f1));如果井深与埋深不一致则输出井深(princ "," f1)(princ fushuwu f1);输出附属物类型(princ " " f1)
输出点表结束后以同样的方式输出线表,鉴于篇幅所限不再赘述。在输出结束后,程序会提醒用户是否直接打开输出的点、线表文件。
(setq kword(getkword " 是否打开文件 是(Y) 否(N):"))(if(=kword "Y")
(progn(startapp " C:/Program Files/Microsoft Office/OFFICE11/Excel.exe" filedb);提示用户打开点表
(startapp"C:/Program Files/Microsoft Office/OFFICE11/Excel.exe" filexb )));提示用户打开线表
5 结 语
通过该程序实现了基于AutoCAD 平台下管线点、线表的自动输出,改变了传统模式需要在AutoCAD 平台完成图形编辑后需要在Excel 中再次进行管点特征信息录入的生产模式。程序利用AutoCAD 扩展数据,使管点信息附着于图块中,可通用于所有的AutoCAD平台。输入、输出信息可以根据需要定义,输出格式可以多样化,能够很方便的移植和扩展,在本单位的地下管线测量实际生产中不仅提高了工作效率,而且提高了准确性,大大节约了工作时间。
当然由于缺乏数据库的支持,本系统对于后期的管线数据管理方面还是要依赖于人工导入到数据库中,在今后的工作中,如何通过属性信息自动生成管线信息扯旗,如何解决同一平面内管点重复编辑等方面应加予探索,通过对程序继续改进,实现更高程度的人工智能化。
[1]马雪萍.地下管线竣工测量中交叉问题的探讨[J].城市勘测,2013(5):143~145.
[2]任航科.LISP 语言在测绘作业中的应用[J].城市勘测,2011(1):110~112.
[3]朱虹.浅谈AutoCAD 与一些常用软件的结合运用[J].科技转让集锦,2010(2).
[4]CJJ61-2003/J271-2003.城市地下管线探测技术规程[S].
[5]浮怀鹏,谭卢师,吴元硕.CAD 图元扩展数据[J].华北水利水电学院学报,2010,31(3):74~75.
[6]刘军,汤永净.城市地下管线探测中遗留问题的分析与处理[J].城市勘测,2013(3).
[7]李洁,秦岩宾,解益辰等.CAD 环境下基于AutoLISP 语言的程序开发[J].测绘与空间地理信息,2013(9).