趙 健 (安徽省水利水電勘測設(shè)計院,安徽 蚌埠 233000)
AutoLISP語言是嵌入在AutoCAD內(nèi)部的LISP編程語言,是LISP語言與AutoCAD有機(jī)結(jié)合的產(chǎn)物。它可以方便調(diào)用AutoCAD的繪圖命令,使設(shè)計和繪圖完全溶為一體;還可以實現(xiàn)對AutoCAD當(dāng)前數(shù)據(jù)庫的直接訪問、修改,為實現(xiàn)對屏幕圖形的實時修改、交互設(shè)計、參數(shù)化設(shè)計以及在繪圖領(lǐng)域中應(yīng)用人工智能提供了方便。
AutoLISP語言繼承了LISP語言擅長處理各種結(jié)構(gòu)的數(shù)據(jù)表的特點,用戶可以按需求來設(shè)計和使用自定義的結(jié)構(gòu)類型數(shù)據(jù)。而且,AutoLISP擅長描述人機(jī)交互操作的過程,對于各種用戶輸入的接受、錯誤識別與恢復(fù)等方面的優(yōu)秀功能(尤其是DCL語言加入以后),其他語言很難在此方面比及。
AutoCAD在啟動時會有一個自動加載的LISP程序,該程序位于CAD安裝目錄下的Support文件夾里,以acadxxxx.lisp的方式命名(xxxx為版本號)。用記事本打開這個文件并加入下面這條語句(vl-load-all"XZS.fas"),CAD則會在“支持文件搜索路徑”所包含的文件夾里尋找“XZS.fas”并加載它(XZS.fas是筆者所編寫的LISP程序)。除此之外,還需要在XZS.fas的源代碼中加入下列語句,以實現(xiàn)自定義的菜單文件XZS.mnu和對話框控制語言文件XZS.DCL的自動加載:
(command"menuload""XZS.mnu");加載菜單
(menucmd(strcat"P"(itoa i)"=+XZS.POP1"));將菜單顯示在菜單欄最后一列
(setq DCL_ID(LOAD_DIALOG"XZS.DCL"))
(NEW_DIALOG"RECT"DCL_ID)
(START_DIALOG)(UNLOAD_DIALOGDCL_ID);加載DCL
接下來,是軟件安裝包的制作。在本文中,安裝包需完成以下任務(wù):①在注冊表中搜索AutoCAD的安裝目錄和版本信息;②提示用戶選擇需要安裝的CAD平臺版本;③將XZS.fas、XZS.mnu和XZS.DCL文件復(fù)制到用戶所選擇的CAD的Support文件夾中;④在Support目錄下的acadxxxx.lsp文件中追加(vl-load-all"XZS.fas")語句。
作為一款功能強(qiáng)大的安裝程序制作工具,Setup Factory可以實現(xiàn)筆者所需要的上述要求。以下是安裝包制作過程中的主要操作代碼:
Reg2004=Registry.GetValue(HKEY_LOCAL_MACHINE,"Software\Autodesk\AutoCAD\R16.0\ACAD-201:804","AcadLocation",false);
Path2004=String.Concat(Reg2004,"\support");
File.Copy(SessionVar.Expand("%TempLaunchFolder%\XZS.fas"),Path2004,true,true,false,true,nil);
TextFile.WriteFromString(String.Concat(Path2004,"\acad2004.lsp"),strLisp,true);
在繪制線狀地物,如水涯線、陡坎時,野外采集的碎部點連線后,顯示的是折點棱角分明的多線段,這和實際地貌是不符的。為了盡可能還原實際地貌,我們需要對多線段進(jìn)行擬合。AutoCAD提供了多種擬合方式,如果直接進(jìn)行擬合操作的話,會導(dǎo)致線條偏離節(jié)點位置較遠(yuǎn)。我們通常的做法是在折點附近手工插入點,以減輕“脫點”現(xiàn)象。
以1:500地形圖為例,當(dāng)一條多線段折角為90°時,在距折點1m處,和多線段成20°夾角的前后位置各插入一點,再用“樣條曲線”方式進(jìn)行擬合,可大幅減輕“脫點”現(xiàn)象。隨著折角逐漸增大,插入點至折點距離可適當(dāng)增加,兩者連線與多線段夾角則逐漸減小。
手工插點是一項繁復(fù)的工作,通過本軟件的“插入節(jié)點”功能,可以讓制圖人員輕松完成這一步。該功能的整體思路為:先將多線段坐標(biāo)寫入到表lst中,然后依次計算每個折點的角度angPnt,根據(jù)地形圖比例尺和angPnt再推算出插入點至節(jié)點的距離disIns1和夾角angIns1,用POLAR函數(shù)計算出插入點坐標(biāo)并存儲在表lstNew中,最后調(diào)用AutoCAD的command命令生成新的多線段。主要實現(xiàn)代碼如下:
;----------計算出插入節(jié)點處角度及距離---------
(if(>angPnt pi)(setq angIns(-(*pi 2)angPnt))(setq angIns angPnt));angIns為改正為<180度角的angPnt
(if(<=angIns(/pi2))
(progn
(setq angIns1(+(/pi12)(*(/1.0 18)angIns)))
(setq disIns1(+0.4(*(/1.2 pi)angIns)))
)
(progn
(setq angIns1(-(/pi9)(*(/19.0 90)(-angIns(/pi2)))))
(setq disIns1(+1(*(/8 pi)(-angIns(/pi2)))))
)
);end if
(setq sca(getvar"ltscale"))
(if(>sca 0.5)
(setq disIns1(*(sqrt(/sca 0.5))disIns1))
)
;-----------插入新節(jié)點----------
(if( (progn (if(<(distance(nth 0 lst)(nth 1 lst))(*disIns1 2))(setq disIns1(/(distance(nth 0 lst)(nth 1 lst))3))) (setq lstNew(cons(polar(nth 0 lst)(+ang1 ang2c angIns1)disIns1)lstNew)) ) );end if (if(>angPnt pi) (progn (if(<(distance(nth 0 lst)(nth 1 lst))(*disIns1 2))(setq disIns1(/(distance(nth 0 lst)(nth 1 lst))3))) (setq lstNew(cons(polar(nth 0 lst)(+ang1(-ang2c angIns1))disIns1)lstNew)) ) );end if ;------生成新LWPOLYLINE------ (setvar"osmode"0) (setvar"cmdecho"0) (apply 'command (cons"pline"lstNew) ) (if(=isClose1) (command"c") (command"") ) 該功能可以根據(jù)特定的命名規(guī)則將地物自動連線,熟練掌握后可節(jié)省大量外業(yè)畫草圖及內(nèi)業(yè)連線的時間。具體規(guī)則如下: ①軟件對點名中地物代碼相同的點進(jìn)行自動連線(如果是高程點或散點應(yīng)以數(shù)字開頭); ②字母c表示地物閉合,z表示到該點結(jié)束,如:k1c,k2z; ③如果一個點代表兩個以上地物,則其之間的分隔符以“/”表示,如:k1/g3; ④往前插入一個點以“-”表示。也可在“-”后加1~9之間的數(shù)字表示回插個數(shù),如:k1-/g3-2。 雖然有的軟件有著類似的功能,如南方CASS中的“簡碼識別”,不過其連線方式不夠靈活。比如在測圖過程中經(jīng)常需要交替跑點,而“簡碼識別”中“N+/N-”連線方法需要在一個地物未測完之前時刻記著采集過的點數(shù)及每個點在哪個位置,這一點在實際工作中很難做到。相比之下,“編碼成圖”在設(shè)計時充分考慮了測圖人員在跑桿時的測點順序和點號命名習(xí)慣,使用起來更加貼合實際、靈活方便。 假設(shè)某點點名是k1-2z/g3,則在軟件中的操作流程見圖3。 ①將點名分隔成k1-2z和g3,存放于表lstName中,并最終獲得地物代碼k1,賦于變量nameCod。 ②遍歷表lstLib,當(dāng)其包含k1且不含有結(jié)束符(“c”或者“z”)時,返回k1后的數(shù)字“1”?!?”表示k1在表lstCor中的位置,隨后將該點的坐標(biāo)追加到lstCor中的1號表中。 ③若在表lstLib中未找到k1或者k1后已有結(jié)束符,則在lstLib中新增表(k1,3),在lstCor中新增3號表(k1,),然后將該點的坐標(biāo)追加到lstCor中的3號表中。 ④最后當(dāng)nameAll中包含“-”和結(jié)束符時,對lstCor相應(yīng)表中的數(shù)據(jù)進(jìn)行重新排序,將結(jié)束符寫人到lstLib對應(yīng)的記錄中。 以下是部分實現(xiàn)代碼: ;---------將坐標(biāo)寫入表lstcor中----------- (setq lstTmp(list(atof(nth 2 lstcode))(atof(nth 3 lstcode)))) (setq lstcor-new'()) (setq i01 0) (repeat(length lstcor) (if(=i01(-isFound 1)) (progn (setq lstTmp(cons lstTmp(nth(-isFound 1)lstcor))) (setq lstcor-new(cons lstTmp lstcor-new)) ) (setq lstcor-new(cons(nth i01 lstcor)lstcor-new)) ) (setq i01(+1 i01)) ) (setq lstcor(reverse lstcor-new)) ;---------當(dāng)nameAll中包含“-“時部分代碼----------- (if(=(length(nth(-isFound 1)lstLib))2) (progn;當(dāng)nameall中不包含結(jié)束符時 (repeat(-(-(length lstcorRe)x)1) (setq lstcor-tmp(cons(nth x lstcorRe)lstcor-tmp)) (setq x(+x 1)) ) ) (progn;當(dāng)nameall中包含結(jié)束符時 (setq lstLib(cons(list namecod(+(length lstLib)1))lstLib)) (setq lstadd(list namecod)) (setq isContainEnd 1) (repeat(-(-(length lstcorRe)x)1) (setq lstadd(cons(nth x lstcorRe)lstadd)) (setq x(+x 1)) ) ) ) 經(jīng)筆者實踐,合理利用本軟件中提供的功能可以方便快速的繪制地形圖,提高處理內(nèi)業(yè)資料時的工作效率。相比之下,“草圖法”在測點順序過于雜亂無章和描述地物相對位置關(guān)系時有著不可替代的優(yōu)越性,而該軟件則在繪制較整狀的帶狀地形圖時更加高效便捷。在剛接觸“編碼成圖”功能時建議草圖和軟件相結(jié)合使用,當(dāng)熟練掌握其點號命名的各種技巧后,則可以有針對性的用編碼替代部分草圖,最終達(dá)到降低內(nèi)業(yè)時間,提高工作效率的目的。2.2 編碼成圖
3 結(jié) 論