陳培龍
(漳州市測繪設計研究院,福建 漳州 363000)
隨著國民經濟的發(fā)展,我國的城市建設也取得了巨大的成就。近年來城市測量工作在城市發(fā)展中的作用越來越突出,而城市地下管線測量作為城市測量工作的重要組成部分,越來越受到相關部門的重視。城市建設的飛速發(fā)展,原有城市地下管線資料欠缺的矛盾越來越突出。因此查明地下管線,并確定其分布、埋深及走向等管點特征信息,建立一個有效的、簡潔的管線信息測量錄入系統,就顯得更加迫切[1]。筆者所在單位進行的管線測量成果一般以Excel 電子表格的形式輸出,而日常測量成圖又是在AutoCAD 平臺下,故筆者利用AutoLISP 編制程序實現AutoCAD 到Excel 的管線點、線表自動輸出,從而提高工作效率。
AutoLISP 是內含于AutoCAD 軟件中的開發(fā)語言,是強化AutoCAD 最好、最直接的程序語言。它最大的特點就是不挑剔編輯環(huán)境,幾乎在所有的文本編輯器中都可以編寫,而且不需要特殊的編譯過程。它的語法結構簡單易懂,變量定義方便、簡潔非常富有彈性。Dcl 是內嵌于AutoCAD 平臺的一款對話框語言,該語言和LISP 一樣,語法結構簡單,不需經過編譯,可以在AutoCAD 平臺下直接調用[2]。使用LISP+Dcl 能夠輕松實現基于AutoCAD 平臺的交互輸入與輸出,功能強大、通俗易用。本系統主要利用AutoCAD 圖元可以擴展數據的功能,對管點圖塊的AutoCAD 屬性進行擴展,從而實現管線點、線表自動輸出[3]。
管線測量一般先外業(yè)采集管點的坐標及高程信息,然后再對各個管點的特征數據進行采集,該系統主要模擬外業(yè)生產流程,根據外業(yè)采集的各特征點信息的流程進行錄入,通過管線的流向方向,實現管線點、線表從CAD 到Excel 的輸出[4]。圖1 為地下管線探測工作流程。
圖1 地下管線探測工作流程圖
AutoCAD 擴展數據是軟件自帶的一種擴展方式,其主要結構方式為:(-3(應用名(1000 .文本型屬性)(1040.浮點型屬性)(1070 .整數型屬性))),應用名可以通過“Regapp”函數直接注冊,如果注冊成功,該應用名會被加入到Appid 符號表中,該表保留了該圖形中所有使用擴展數據的應用名[5]。對話框是現今最流行的人機互動界面,在早期的AutoCAD 版本中已經使用,對話框的描述定義在一純文本文檔(后綴名為.dcl)內,無須特別的開發(fā)環(huán)境,稱之為Dcl 語言。在AutoLISP 中內嵌可以直接控制Dcl 對話框的函數,對話框中的每一個對象均有一個唯一的標示符即Dcl 主鍵名稱,通過主鍵名稱,就可以準確的控制對話框的各個部件。對于擴展數據結構及主鍵的定義如表1 所示。
擴展數據結構及Dcl 主鍵一覽表 表1
管線外業(yè)采集一般使用全站儀或者GPS 進行采集,采集數據包含測點點名,編碼,北坐標X,東坐標Y,高程值H。外業(yè)采集的同時需要根據管井的井蓋等信息判斷出管井的類型,例如污水、雨水、電力、電信、燃氣等,然后再對管井進行探測以便采集管點的屬性信息如管徑、埋深、井深、電纜根數、電纜孔數等[6],依據這些采集的數據,通過使用自動展繪模塊快速成圖。對于使用該模塊,首先每一種管點類型都先約定一個字母代碼,如污水管點為W,雨水管點為Y,電力管點為L 等。在內業(yè)處理時首先編輯對照文件,文件為文本格式,當文本中出現管點字母代碼時,表示該代碼后的所有測點點名都是該類型管點,每一行表示一個點名,直到出現其他管點字母代碼。
例如:Y
表示點名為100、101 的測點為雨水管點,103、104為污水管點。完成點、線表對照文件編輯后,就可以通過自動展繪管點圖塊程序,完成管點圖塊的CAD 成圖,同時錄入該點的高程值和外業(yè)點名。模塊界面如圖2 所示:
圖2 自動畫管線的界面
管點展繪后效果如圖3 所示:
圖3 管點展繪效果圖
完成管點圖塊繪制后,需要根據管線實地的連接方向進行連線。AutoCAD 的二維多段線會根據每個端點繪制的順序形成一個方向,在管點流向繪制時,需保證管點流向的方向與二維多段線的方向保持一致,例如:雨水管線從上游往下游方向繪制,并保證二維多段線每個端點均與管點圖塊的中心點一致,這樣就在繪制流向的同時也就完成了原來互相獨立的管點之間拓撲關系的連接。
如果管線的類型是雨水或者污水,那么在完成流向繪制后,還需要在每兩個管點之間繪制一個表示流向的箭頭。為了保證箭頭的一致性和美觀性,程序還提供了自動畫流向箭頭功能,同時約定在兩個管點距離大于等于5 m的情況下,箭頭長度為1.6,距離小于5 m時,箭頭長度縮小為0.6,并保證箭頭的頂端位于兩管點流向線的中點上,與流向線兩側的夾角均為20°。由于AutoCAD 二維多段線的方向沒有直觀地顯示,故在實際操作中會出現二維多段線的方向與流向的方向相反的情況,為了防止這種情況的出現,在流向箭頭繪制程序運行的最后會在命令行提示用戶判斷繪制箭頭的方向是否正確,若用戶選擇為否(N),則程序會對該流向線進行反向處理,并重新繪制正確的箭頭。同時還提供SCJT(刪除箭頭)命令,可以刪除最后繪制的一組箭頭,最大限度減少誤操作帶來的重復勞動。
管點在圖形中主要靠管點的編號來識別,因此管點編號的條理性及準確性就顯得特別重要。在將管線數據以Excel 表格方式輸出后,如何快速將文本數據與AutoCAD 圖形聯系起來,跟管點編號的方式有很大的關系。為了能更快速、準確、對管點進行編號,程序提供了自動編號模塊。運行命令時,首先提示用戶選擇需要編號的流向線,然后根據用戶輸入的起始編號,程序會按照流向線方向對線上每個管點進行遞增編號。例如:用戶輸入雨水管點起始編號為Y10D100,程序會對接下去的管點編號為Y10D101、Y10D102……,如圖4 所示。
圖4 自動畫流向箭頭效果圖
完成上述工作后,就需要對外業(yè)采集的管點屬性信息進行錄入。管點的屬性錄入界面如圖5 所示。一般管線測量只有電力和電信需要錄入共有孔數、已用孔數、電纜根數這三個屬性信息,在程序的運行中,會根據管點的圖塊名稱自動判斷出管線類型,如果是電力或電信,則共有孔數、已用孔數、電纜根數三項可以錄入信息;如果是雨水或者污水等其他類別的管線則錄入框會以灰色不可編輯框的形式出現。預留擴展在程序執(zhí)行中會以不可編輯框的形式出現,預留擴展是為預防后期管線錄入屬性增多而準備的,需要使用時必須修改后臺程序后才能錄入信息,應用本文所提的方法,可以根據需要任意擴展。
圖5 管點屬性信息錄入界面
完成所有的屬性錄入工作后,就可以輸出點線表了。程序約定輸入的點、線表自動存放于當前活動圖形的同級目錄下,并命名為輸出點表.csv 和輸出線表.csv。用戶可以連續(xù)選擇需要輸出的流向線,右鍵結束選擇后,程序將根據選擇的流向線,自動輸出該線上所有管點的屬性信息[7]。
當輸出的管線類型為雨水或者污水時,程序會對各點井底高程就行復查,當管點的井底高程大于上一管點井底高程的數值超過某一閾值時(默認設置設為10 cm),會在該行線表的備注欄標注“流不出”,提示用戶進行人工再確認,防止出現粗差。由于在連線時已經將流向與二維多段線的方向保持一致,故每次雨、污的流向均為正向。輸出效果如圖6 所示:
圖6 線表輸出效果圖
(setq ssjiantou(ssadd));創(chuàng)建一個集合,將所有箭頭放在這個集合內
(setq a(car(entsel)));選擇需要畫箭頭的流向線
(setq leixing(cdr(assoc 0(entget a))));判斷對象是否為多段線
(if(=leixing "POLYLINE")(progn
(setq tuceng(cdr(assoc 8(entget a))));判斷所在圖層
(panduan);判斷模塊,如果不是雨水或者污水,則程序不再執(zhí)行
(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));訪問下一個子圖元,繼續(xù)繪制箭頭
(setq over(cdr(assoc 0(entget en)))));判斷子圖元是否結束
(initget 0 "Yes No")
(setq keyw(getkword " 流向方向是否正確[是(Y)/否(N)]:")));用戶確定方向
(alert "您選擇的不是多段線");如果選擇的不是多段線則提醒
)
(if(=keyw "No")(chongxinhua));如果用戶選擇流向方向為不正確,則反向重畫
(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))))))))
(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);輸出外業(yè)點號(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 )));提示用戶打開線表
通過該程序實現了基于AutoCAD 平臺下管線點、線表的自動輸出,改變了傳統模式需要在AutoCAD 平臺完成圖形編輯后需要在Excel 中再次進行管點特征信息錄入的生產模式。程序利用AutoCAD 擴展數據,使管點信息附著于圖塊中,可通用于所有的AutoCAD平臺。輸入、輸出信息可以根據需要定義,輸出格式可以多樣化,能夠很方便的移植和擴展,在本單位的地下管線測量實際生產中不僅提高了工作效率,而且提高了準確性,大大節(jié)約了工作時間。
當然由于缺乏數據庫的支持,本系統對于后期的管線數據管理方面還是要依賴于人工導入到數據庫中,在今后的工作中,如何通過屬性信息自動生成管線信息扯旗,如何解決同一平面內管點重復編輯等方面應加予探索,通過對程序繼續(xù)改進,實現更高程度的人工智能化。
[1]馬雪萍.地下管線竣工測量中交叉問題的探討[J].城市勘測,2013(5):143~145.
[2]任航科.LISP 語言在測繪作業(yè)中的應用[J].城市勘測,2011(1):110~112.
[3]朱虹.淺談AutoCAD 與一些常用軟件的結合運用[J].科技轉讓集錦,2010(2).
[4]CJJ61-2003/J271-2003.城市地下管線探測技術規(guī)程[S].
[5]浮懷鵬,譚盧師,吳元碩.CAD 圖元擴展數據[J].華北水利水電學院學報,2010,31(3):74~75.
[6]劉軍,湯永凈.城市地下管線探測中遺留問題的分析與處理[J].城市勘測,2013(3).
[7]李潔,秦巖賓,解益辰等.CAD 環(huán)境下基于AutoLISP 語言的程序開發(fā)[J].測繪與空間地理信息,2013(9).