盛 杰 陳樹林 李國平
(江西省地礦測繪院 江西南昌 330030)
在測繪領(lǐng)域中,AutoCAD是一款常用的繪圖軟件,它常用于地圖的編圖、成圖等圖形處理操作。雖然它在成圖制圖方面能很好的滿足需要,但AutoCAD不是一款專業(yè)的測繪軟件,不具備測繪有關(guān)的功能。比如AutoCAD自身并不具備拓?fù)錂z查功能,然而對于地圖編圖、成圖來說,拓?fù)錂z查是成圖、入庫的基礎(chǔ),是一個必不可少的要求。所幸的是AutoCAD支持二次開發(fā),我們可以通過基于AutoCAD二次開發(fā)的方式擴展AutoCAD的功能,編寫用戶自定義工具。
研究現(xiàn)狀。由于CAD軟件廣泛應(yīng)用于測繪領(lǐng)域的成圖,已有相關(guān)學(xué)者及技術(shù)人員針對CAD平臺下懸掛檢查與處理的問題做過研究并給出了很好的解決方法。在當(dāng)時的技術(shù)背景下確實是很好的解決方案。但隨著CAD二次開發(fā)技術(shù)的不斷進步,特別是AutoCAD.NET API的發(fā)布,采用最新的AutoCAD.NET技術(shù)不論在程序執(zhí)行效率還是在開發(fā)效率上都有了顯著提升,能更好的解決此問題。
在《在AutoCAD中懸掛點的檢查方法》及《基于CAD平臺開發(fā)的懸掛點檢查與自動處理》的論文中,分別采用AutoLISP和ObjectARX的方式解決問題。但采用AutoLISP程序執(zhí)行效率略低,在處理大量數(shù)據(jù)是速度較慢,而采用ObjectARX技術(shù)雖然有著較高的執(zhí)行效率,但開發(fā)難度較大,較為復(fù)雜,開發(fā)周期長,開發(fā)人員需要掌握 VC++[2]。在《基于 CAD平臺開發(fā)的懸掛點檢查與自動處理》一文中,雖然給出了很好的解決方案,但算法、邏輯對于普通測繪人員來說過于復(fù)雜,難以掌握,并且還是采用C++的開發(fā)方式,這就更令測繪人員望而卻步,難以在測繪領(lǐng)域為廣大測繪人員掌握、應(yīng)用;而AutoCAD.NET采用程序集的方式直接調(diào)用,在擁有與C++相匹配的強大功能與效率的同時,還具有.NET簡單易學(xué)易用的特點,使開發(fā)更為簡單開發(fā)周期更短[1]。
當(dāng)然也有人士提出采用AutoCAD.NET的方式處理懸掛點的問題,在《AutoCAD中一種自動處理懸掛的方法及其實現(xiàn)》一文中,采用的就是NET方式解決此問題。但作者在文中提出存在因線型(如虛線)導(dǎo)致懸掛點判斷錯誤的問題[5]。本文采用線型預(yù)處理及恢復(fù)線型的方式很好的解決了此問題。并采用與之不大相同的方式對懸掛點進行自動處理,使其有更高的執(zhí)行效率以及更廣的實用范圍。
開發(fā)語言:C#;開發(fā)平臺:Visual Stdio;調(diào)用CAD.NET API,實現(xiàn)程序功能。另外還調(diào)用AutoCAD ActiveX Automation(COM)組件的一些方法,來實現(xiàn)自定義菜單的添加。
懸掛點就是線段的端點附近無其它線與之相連的點。因此,懸掛點的檢查方法可以通過查找每一條線段的兩端點在一定緩沖區(qū)范圍內(nèi)有無其它線來實現(xiàn)。具體步驟如下:
(1)新建項目
新建一個類庫項目,然后添加AutoCAD安裝目錄下的acdbmgd.dll和acmgd.dll程序集的引用,以及CAD組件的引用。
(2)查找、遍歷所有的多段線
通過設(shè)置一個過濾條件(SelectionFilter),查找所有的可見多段線(Polyline)。
(3)判斷線段的端點是否懸掛的方法
假設(shè)某線段的端點為P(x,y),定義一個極小的緩沖范圍:tol=0.0000001,在由(x-tol,y-tol)、(x+tol,y+tol)確定的矩形內(nèi),如果沒有任何其它多段線與該矩形相交,則認(rèn)為該點懸掛。如圖1所示:
圖1 判斷端點是否懸掛
實現(xiàn)代碼:
通過SelectCrossingWindow函數(shù),獲得與上圖矩形區(qū)域相交的所有多段線。
PromptSelectionResult acSSPrompt=acDocEd.SelectCrossingWindow(new Point3d(point.X-tol,point.Y-tol,0),new Point3d(point.X+tol,point.Y+tol,0),acSelFtr);
遍歷該選擇集,如果該選擇集存在圖形的OBjectID不等于該多段線的OBjectID,則該端點不懸掛。否則,該端點懸掛。
(4)進行懸掛分析之前的圖形預(yù)處理
在使用SelectCrossWindow函數(shù)時,需要注意一下幾個問題:
1)SelectCrossWindow函數(shù)是在當(dāng)前視圖的范圍內(nèi),獲取兩點定義的區(qū)域。
也就是說,當(dāng)某線段端點不在當(dāng)前視圖范圍內(nèi),其分析結(jié)果必然是個空集。從而導(dǎo)致分析結(jié)果的錯誤;另外,當(dāng)圖形縮放的很小,圖形元素非常的密集,某線段端點的緩沖范圍內(nèi)會分析出大量的多段線。當(dāng)圖形縮放到合理范圍時,在該緩沖區(qū)范圍內(nèi)是不存在這么多多段線的。因此,這也會導(dǎo)致懸掛判斷的錯誤。
為解決上述問題,可以在對某端點進行懸掛判斷之前,先將視圖縮放到該端點附近范圍。這樣就會得到正確的結(jié)果。
2)特殊的線型與線寬也會導(dǎo)致SelectCrossing-Window函數(shù)得到錯誤的結(jié)果,如圖2所示,由于要比較的多段線為虛線,導(dǎo)致多段線端點的緩沖區(qū)范圍內(nèi),不存在與之相交的其它多段線,而得到錯誤的結(jié)果;
圖2 線型導(dǎo)致懸掛判斷錯誤
同樣,如圖3所示,由于線寬太粗,CAD會判定其與緩沖區(qū)不相交,也會得到錯誤的結(jié)果。
圖3 線寬導(dǎo)致懸掛判斷錯誤
為解決此問題,可以在懸掛分析前,將所有非實線線型以及所有寬度大于0的多段線,都轉(zhuǎn)化成線型為實線,寬度為0的多段線。并將所有被修改過多段線的 ObjecctID、線型 (LineTypeId)、以及線寬(ConstantWidth)存儲在數(shù)組變量中。以便在分析完成后,對線型、線寬的恢復(fù)。
(5)懸掛分析、分析結(jié)果展示、恢復(fù)線型線寬
采用步驟(3)的方法,對每條多段線的兩端點進行懸掛分析,然后將存在懸掛的端點插入一個懸掛標(biāo)記;并將所有的懸掛點放在一個列表框內(nèi),當(dāng)選中某項時,視圖就會自動縮放到該懸掛點,以便于對每個懸掛點的查找。最后,恢復(fù)步驟(4)改變的線型和線寬。分析結(jié)果如下圖4所示。
圖4 懸掛檢查效果圖
(1)定義一個比判斷端點懸掛更大的緩沖區(qū)范圍,然后在該緩沖區(qū)范圍內(nèi),查找有無其它多段線與該緩沖區(qū)范圍相交,如圖5所示。如果存在,則對該懸掛點進行自動處理。
圖5 懸掛點的自動處理
(2)找出該多段線上離懸掛點最近的點:N,如圖5所示。點N可通過調(diào)用該多段線的GetClosetPointTo函數(shù)來獲得。代碼如下:其中point為懸掛點。
Point3d nearPoint= polyline.GetClosestPointTo(point,false);
(3)求出最近點 N在多段線上的曲線參數(shù)parameter:
double parameter=polyline.GetParameterAtPoint(nearPoint);
然后根據(jù)曲線參數(shù),求得鄰近兩節(jié)點A、B的節(jié)點序號。假設(shè)該多段線的起點是S,終點是E,則A點的節(jié)點序號aIndex為parameter的整數(shù)部分。
int aIndex=(int)Math.Floor(parameter);
B點的節(jié)點序號bIndex為parameter的整數(shù)部分加1。
int bIndex=(int)Math.Floor(parameter)+1;
最后通過該多段線的GetPoint3dAt函數(shù),就可獲得A、B兩個節(jié)點。
(4)判斷 A、B 兩點是否在步驟(1)設(shè)定的緩沖區(qū)范圍內(nèi)。如果在,如上圖5所示,B點在該緩沖區(qū)范圍內(nèi),則移動懸掛點P到B點,消除該懸掛點??赏ㄟ^調(diào)用多段線的SetPointAt函數(shù)來修改P點的坐標(biāo)。
(5)如果 A、B 兩點不在步驟(1)設(shè)定的緩沖區(qū)范圍內(nèi),則在步驟(3)中的bIndex序號處,將最近點N作為新節(jié)點,插入到該多段線中 (調(diào)用多段線的AddVertexAt函數(shù)來實現(xiàn)節(jié)點插入);然后將懸掛點P移動到N點,進而消除該懸掛點。
與懸掛點檢查類似,懸掛點的自動處理之前,也需要將視圖縮放到各懸掛點附近范圍;并調(diào)整非規(guī)則的線型與線寬,在此就不再贅述。
繼續(xù)圖4的懸掛點處理,點擊“自動處理所有懸掛”按鈕。處理后,結(jié)果如下圖6所示。與之前懸掛點個數(shù)742相比,剩下314個懸掛點需要手工處理,程序共自動處理了428個懸掛點達(dá)到了預(yù)期目標(biāo)。
圖6 自動處理懸掛點效果圖
針對不同比例尺的地圖,各自的懸掛點檢查以及懸掛點自動處理的緩沖區(qū)范圍(分別如圖1、圖5所示)也應(yīng)該有所不同。如小比例尺的地圖要設(shè)置較大的緩沖區(qū),大比例尺的地圖要設(shè)置較小的緩沖區(qū),這樣才能滿足各自的需要。因此,為滿足不同比例尺下懸掛處理的要求,本程序?qū)⒕彌_區(qū)范圍設(shè)置成可供用戶修改設(shè)置的變量,從而滿足不同比例尺地圖的要求,如下圖7所示:
圖7 設(shè)置緩沖區(qū)范圍
該程序經(jīng)我院“湖南不動產(chǎn)登記DLG數(shù)據(jù)采集與入庫項目”使用,平均每幅圖懸掛點檢查用時4秒,能查出所有懸掛點,約700個;懸掛點自動處理用時5秒,能自動處理掉約400個懸掛點。
(1)從程序正確性來看,程序能正確找出圖幅內(nèi)的所有懸掛點,無遺漏;并且能自動正確處理掉大部分的懸掛點,達(dá)到了預(yù)期效果。
(2)從程序執(zhí)行速度來看,采用.NET的CAD開發(fā),與前幾代的AutoCAD開發(fā)技術(shù)相比,具有更高的執(zhí)行效率。程序的查圖、處理速度快,速度上令人滿意,程序設(shè)計的算法切實可行。
(3)作為CAD下的一個拓?fù)錂z查與處理工具,該程序可用于其他項目地圖的懸掛點檢查與自動處理,具有較強的實用性。
結(jié)論:該程序解決了項目成果存在的懸掛點多,查找困難,處理費時費力的問題;大大提升了項目拓?fù)錂z查與處理工作效率,節(jié)約了項目查圖、入庫人力成本;提高了項目成果質(zhì)量。