劉學杰,張福利
(河南省中緯測繪規(guī)劃信息工程有限公司,河南 焦作 454000)
基于VB.NET的房屋擴展數(shù)據(jù)自動掛接方法
劉學杰,張福利
(河南省中緯測繪規(guī)劃信息工程有限公司,河南 焦作 454000)
在AutoCAD平臺下大比例尺地圖制圖中,房屋作為重要的地物要素,不僅需要圖面注記樓層、建筑結(jié)構(gòu)等文字信息,而且要在內(nèi)部附加符合地理信息系統(tǒng)要求的擴展信息。本文系統(tǒng)闡述了使用編程的方法,通過對AutoCAD二次開發(fā)將房屋文字注記轉(zhuǎn)換為圖形內(nèi)部擴展信息的實現(xiàn)原理及程序開發(fā)設計過程,為廣大測繪工作者提高生產(chǎn)效率開辟新的工作思路。
VB.NET;AutoCAD;房屋屬性;擴展數(shù)據(jù);自動掛接;選擇集
目前隨著制圖軟件技術(shù)的發(fā)展,以及全國性的城鎮(zhèn)地籍調(diào)查、集體土地使用權(quán)確權(quán)工作的開展,各地區(qū)對房屋測繪要求也呈現(xiàn)多樣化趨勢,針對房屋測繪主要體現(xiàn)在成圖軟件多樣化、房屋注記形式多樣化、入庫數(shù)據(jù)格式多樣化,一套軟件將很難完成所有工作。在基于AutoCAD的大比例尺地圖制圖中,房屋是由不規(guī)則的多邊形和房屋屬性注記組成,其中多邊形是房屋空間位置、形狀、大小的抽象描述,注記則是房屋結(jié)構(gòu)、樓層屬性的圖面表述。當房屋僅用作DLG線劃圖制作時,房屋屬性采用圖面注記表達即可滿足要求;而當房屋進行GIS入庫工作時,就需要將房屋內(nèi)部注記的結(jié)構(gòu)、樓層轉(zhuǎn)換為符合地理信息系統(tǒng)要求的擴展信息。
AutoCAD具有開放的體系結(jié)構(gòu),AutoCAD ActiveX提供了從AutoCAD內(nèi)部或外部以程序設計的方法來操作ActiveX自動化對象模型,允許用戶和開發(fā)者采用高級編程語言對其進行擴充和修改。本文通過對房屋多邊形與圖面注記關(guān)系,以及AutoCAD對象模型的定義等進行分析,采用基于VB.NET的二次開發(fā)不僅可以實現(xiàn)AutoCAD智能識別并自動批量掛接房屋屬性信息,而且可最大限度地滿足用戶的特殊要求,顯著地減少了人工逐個轉(zhuǎn)換的工作量。
在基于VB.NET的面向?qū)ο蟪绦蚓帉懼?,需要了解對象的屬性、方法和事件。AutoCAD對象模型中的對象具有一個或多個屬性,以多段線為例,可以用長度、拐點、線寬等來描述,其所具有的特征稱為“屬性”,如Application、Length、Coordinates、Lineweight、Area、Color、Layer等。在ActiveX函數(shù)中要獲得AutoCAD圖形對象的有關(guān)特征就要用到對應的屬性名稱;對象的方法用來指定對象的執(zhí)行方式,即要對ActiveX的對象進行怎樣的操作,如多段線的方法包括Copy、Delete、GetXData、SetXData等。
1. Coordinates屬性
多段線在AutoCAD中對應的是LightweightPolyline對象,Coordinates是其屬性之一,它是個維數(shù)可變的一維雙精度數(shù)組,存儲了多段線在OCS坐標系統(tǒng)下的二維拐點數(shù)組。獲取多段線所有拐點的方法為Object.Coordinates,返回一個Object類型的數(shù)組,包含了對象從起點開始按X、Y序列排列的每個拐點坐標數(shù)據(jù)。
2. SetXData方法
向?qū)ο筇砑踊蛐薷臄U展數(shù)據(jù)可以使用SetXData方法,其定義為:Object.SetXData(XDataType,XData)。其中,XDataType是一個short類型變量數(shù)組,數(shù)組中的每個元素用于說明擴展數(shù)據(jù)的類型;XData是一個Object類型的數(shù)組,數(shù)組中每個元素包含擴展數(shù)據(jù)的內(nèi)容,XDataType中的元素一一對應地說明Xdata中元素的類型。
3. GetXData方法
獲取對象的擴展數(shù)據(jù)可以使用GetXData方法,其定義為:Object.GetXData(AppName,XDataType,XDataValue)。其中,AppName指定添加擴展數(shù)據(jù)的應用程序名稱,如果輸入一個空字符串表示要獲得所有應用程序添加的擴展數(shù)據(jù);XDataType返回一個short類型的數(shù)組,包含對象擴展數(shù)據(jù)的類型信息;XDataValue返回一個Object類型的數(shù)組,包含對象的擴展數(shù)據(jù)。
選擇集對象SelectionSet是AutoCAD與用戶操作的重要手段,它是一個或多個AutoCAD對象組成的集合,可以指定為一個單一的單元用于處理。選擇集允許用戶同時選擇多個圖形對象,并提供豐富的手段來選擇符合特定條件的實體。
1. 對象選擇的方法
要創(chuàng)建一個選擇集,可使用SelectionSets集合的Add方法。在創(chuàng)建選擇集時,如果存在同名的選擇集,AutoCAD將返回一條錯誤的信息,因此,要及時刪除不再需要的選擇集,刪除一個選擇集,可以使用SelectionSet對象的Delete方法。對象選擇的方法很多,Select方法允許用戶選擇所有對象、窗口內(nèi)的對象、位于矩形區(qū)域內(nèi)或與其相交的對象、位于多邊形區(qū)域內(nèi)或與其相交的對象等;SelectBypolygon方法選擇多邊形區(qū)域內(nèi)的對象,并將其添加到活動的選擇集中。選擇集對象為程序編寫提供了5種選擇模式,分別為:AcselectionSetwindows、AcselectionSetcrossing、AcselectionSetprevious、AcselectionSetlast、AcselectionSetall。
本文中用到的主要是AcselectionSetwindows窗口選擇模式,即以多邊形拐點作為窗口角點,選中窗口內(nèi)全部實體,即SSet.SelectByPolygon(AcselectionSetwindows, pointArrs)。
2. 對象選擇的過濾
對象選擇的過濾就是對象選擇時的過濾規(guī)則,可以同時指定多個過濾條件,支持帶有通配符的過濾條件,并且可使用邏輯運算符將多個條件進行組合。如使用AcselectionSetwindows模式選擇多邊形框內(nèi)的對象,并且對象只選擇圓弧、圓、橢圓的代碼如下:
Dim FilterType(4) As Short, FilterData(4) As Object
FilterType(0)=-4: FilterData(0)=" ′邏輯運算符的開始,表示一個或多個運算對象 FilterType(1)=0: FilterData(0)="Arc" FilterType(2)=0: FilterData(0)="Circle" FilterType(3)=0: FilterData(0)="Ellipse" FilterType(4)=-4: FilterData(0)="or>" SSet.SelectByPolygon(AcSelect.AcselectionSetwindows,pointArrs,FilterType,FilterData) 1. 房屋多邊形建立選擇窗口 前文中知道房屋多邊形對象有個重要屬性Coordinates,存儲了構(gòu)成多段線所有拐點的二維坐標,如圖1所示,多段線坐標存儲結(jié)構(gòu)為從起點開始按拐點次序依次排列的X1、Y1、X2、Y2、X3、Y3、…、Xn、Yn坐標數(shù)據(jù)。建立多邊形選擇窗口時,多邊形窗口在圖形中是虛擬化的,僅需知道組成窗口的多邊形拐點坐標數(shù)據(jù)即可,而不必繪制出多邊形,與房屋多邊形比較其拐點坐標為三維坐標(用0值代替Z值),對于封閉窗口還需增加一個末點,末點坐標應該與起點坐標相一致。多邊形選擇窗口的坐標需存儲在雙精度類型的一維數(shù)組中,如圖2所示,其存儲格式為X1、Y1、0、X2、Y2、0、X3、Y3、0、…、X1、Y1、0。 圖1 多段線拐點坐標存儲結(jié)構(gòu) 圖2 選擇窗口坐標存儲結(jié)構(gòu) 2. 房屋注記提取結(jié)構(gòu)和樓層 大比例尺地圖制圖時房屋注記的形式是多樣化的,依據(jù)現(xiàn)行的規(guī)范、規(guī)程和地方規(guī)定,房屋注記的樣式總結(jié)有3種形式:①結(jié)構(gòu)和樓層分離表示,如圖3所示,“混”表示房屋的結(jié)構(gòu),“2”表示房屋樓層,結(jié)構(gòu)與樓層為單獨的字符;②結(jié)構(gòu)和樓層合并表示,如圖4所示,“混2”用字符串表示結(jié)構(gòu)和樓層;③采用分數(shù)形式的字符串表示,如圖5所示,分母“4”表示結(jié)構(gòu),分子“2”表示樓層。程序設計時,以組成房屋的多邊形為選擇窗口,過濾選擇房屋注記所在圖層上的全部字符,然后遍歷所選字符對象,針對圖3首先判斷文字是否為關(guān)鍵字“混”,若是就提取出房屋結(jié)構(gòu),否則進一步判斷該字符是否為數(shù)字,若是就提取出房屋樓層;針對圖4,相對圖3僅需要用代碼將字符串分解為2個部分,然后依次判斷即可;對于圖5,可以通過判斷字符串內(nèi)是否包含關(guān)鍵字“/”,以“/”為分割符,分別截取分子(樓層)和分母(結(jié)構(gòu))。 圖3 結(jié)構(gòu)與樓層分離注記 圖4 結(jié)構(gòu)與樓層合并 圖5 分數(shù)形式注記 3. 擴展數(shù)據(jù)中表示房屋屬性 AutoCAD中擴展數(shù)據(jù)的引入為圖形提供了GIS的屬性管理能力,對象的SetXData方法可以為房屋添加1個或N個自定義的擴展數(shù)據(jù),如結(jié)構(gòu)、樓層、年代、編號等,擴展數(shù)據(jù)由開發(fā)者自行定義和解釋,AutoCAD只維護這些數(shù)據(jù)而不管其具體含義,擴展數(shù)據(jù)可以是字符串、實數(shù)、整數(shù)等。這樣不僅節(jié)省了圖面注記占用的空間,而且為二次開發(fā)批量處理數(shù)據(jù)提供了技術(shù)保障。 SetXData方法中,參數(shù)XDataType用于說明擴展數(shù)據(jù)的類型,所支持的DXF組碼只能采用1000~1071之間的組碼值,不同的組碼對應不同的類型信息。以下為某制圖軟件中一房屋的擴展數(shù)據(jù)記錄: * Registered Application Name:SOUTH-(1) * Code 1000, ASCII string: 141161---(2) * Code 1040, Real number: 2.0000----(3) 第一行表示下列擴展數(shù)據(jù)的注冊程序名稱為“SOUTH”;第二行規(guī)定了數(shù)據(jù)為字符類型,值為“141161”,實際表示房屋的編碼為141161;第三行中規(guī)定了數(shù)據(jù)為浮點類型,值為“2.0000”,實際表示房屋的樓層為2層。 4. 程序開發(fā)設計代碼組織編寫 程序中重復執(zhí)行的代碼可定義為過程或函數(shù),能顯著提高程序的運行效率,當以房屋為遍歷對象并建立選擇集窗口時,設計一個創(chuàng)建選擇集的過程和一個轉(zhuǎn)換多段線為選擇窗口坐標的函數(shù)。代碼如下: Private Sub CreateSset(ByVal Sname As String, ByRef Sset As AcadSelectionSet) Try ′創(chuàng)建新的選擇集或引用一個同名選擇集并清空選擇集對象 Sset=myacadapp.ActiveDocument.SelectionSets.Add(Sname) Catch ex As System.Exception Sset=myacadapp.ActiveDocument.SelectionSets.Item(Sname) Sset.Clear(): Err.Clear() End Try End Sub Private Function GetPcood_ary(ByVal objline As AcadEntity) As Double()′將房屋多段線轉(zhuǎn)為選擇窗口坐標數(shù)組 Dim pointArrs() As Double=Nothing, k As Integer=-1′定義存儲選擇窗口坐標的數(shù)組 Dim getpt As Object=objline.Coordinates ′讀取多段線拐點坐標值到數(shù)組中 For i As Integer=0 To UBound(getpt) Step 2′變換數(shù)組 k+=1: ReDim Preserve pointArrs(k): pointArrs(k)=getpt(i) k+=1: ReDim Preserve pointArrs(k): pointArrs(k)=getpt(i + 1) k+=1: ReDim Preserve pointArrs(k): pointArrs(k)=0.0# Next i If objline.Closed=True Then k+=1: ReDim Preserve pointArrs(k): pointArrs(k)=getpt(0) k+=1: ReDim Preserve pointArrs(k): pointArrs(k)=getpt(1) k+=1: ReDim Preserve pointArrs(k): pointArrs(k)=0.0# End If Return pointArrs End Function 在主程序中,首先設定過濾條件,將符合要求的房屋多段線添加到一個選擇集變量中;然后遍歷選擇集中的所有房屋多段線并建立新的選擇窗口,將該窗口內(nèi)的所有符合條件的文字添加到新的選擇集中;再遍歷新選擇集中的文字,依據(jù)文字注記的特征及級別分離出房屋結(jié)構(gòu)和房屋樓層,如分數(shù)形式的注記級別最高,一旦遍歷到分數(shù)文字,立即解析結(jié)構(gòu)和樓層并退出循環(huán)體。 主程序中Srtxt.LastIndexOf("/")函數(shù)可以查找字符串中是否包含指定字符,能協(xié)助判斷出文字是否為分數(shù)注記;Srtxt.Length函數(shù)能計算字符串內(nèi)字符的數(shù)量,以此忽略3個以上字符的字符串;IsNumeric(Srtxt)函數(shù)可判斷指定的字符是否為數(shù)字。以下為主程序的完整代碼: Private Sub ButtonSetdata_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSetdata.Click Dim sset As AcadSelectionSet=Nothing′定義一個選擇集變量,用于選擇所有房屋 Dim FilterType(1) As Short, FilterData(1) As Object′定義選擇集過濾器變量 FilterType(0)=0: FilterData(0)="LWPOLYLINE" ′添加過濾條件:多段線 FilterType(1)=8: FilterData(1)="FW" ′添加過濾條件:FW層 CallCreateSset("sset",sset) ′調(diào)用自定義過程,建立或引用選擇集 set.Select(AcSelect.acSelectionSetAll, , , FilterType, FilterData)′選擇圖形中符合過濾條件的實體 For Each objline As AcadLWPolyline In sset′遍歷所有選擇集中的多段線(房屋) Dim pointArrs() As Double=GetPcood_ary(objline)′調(diào)用自定義函數(shù)轉(zhuǎn)換多段線為選擇窗口坐標 Dim House_jg As String=Nothing, House_lc As Double=1′定義房屋結(jié)構(gòu)、房屋樓層變量并初始化 Dim Keywd_bm() As String={"141141", "141111", "141161", "141121", "141151"}′定義存儲房屋編碼的數(shù)組 Dim Keywd_jg() As String={"鋼", "砼", "混", "磚", "木"}′定義存儲房屋結(jié)構(gòu)(文字)的關(guān)鍵字數(shù)組 Dim Keynm_jg() As String={"1", "3", "4", "5", "6"}′定義存儲房屋結(jié)構(gòu)(分母)的關(guān)鍵字數(shù)組 FilterType(0)=0: FilterData(0)="TEXT"′修改過濾條件:文字 FilterType(1)=8: FilterData(1)="TZFG"′修改過濾條件:TFZG層 Dim stxt As AcadSelectionSet=Nothing:Call CreateSset("stxt", stxt) stxt.SelectByPolygon(AcSelect.acSelectionSetWindowPolygon, pointArrs, FilterType, FilterData) For Each Lstxt As AcadText In stxt′遍歷多段線內(nèi)部的所有文字注記 Dim Srtxt As String=Lstxt.TextString′讀取文字對象的注記內(nèi)容 If Srtxt.LastIndexOf("/") <> -1 Then′查找文字注記是否含字符′/′ House_jg=Mid(Srtxt, InStr(1, Srtxt, "/") + 1)′獲取房屋建筑結(jié)構(gòu) House_jg Keywd_jg(Array.IndexOf(Keynm_jg, Hours_jg))′轉(zhuǎn)換結(jié)構(gòu)為漢字形式 House_lc=CDbl(Mid(Srtxt, 1, InStr(1, Srtxt, "/") - 1))′獲取房屋樓層數(shù) Exit For′符合條件后,退出循環(huán),提高運行效率 Else If IsNumeric(Srtxt)=True Then′判斷文字為數(shù)字 House_lc=CDbl(Srtxt)′如是就提取寫入樓層變量 Else House_jg=Mid(Srtxt, 1, 1)′讀取字符串中的第一個字符 If System.Array.IndexOf(Keywd_jg, House_jg) <> -1 Then′判斷是否符合關(guān)鍵字 If Srtxt.Length=2 Then′判斷文字長度是否等于2 House_jg=Mid(Srtxt, 1, 1)′獲取房屋建筑結(jié)構(gòu) House_lc=CDbl(Mid(Srtxt, 2, 1))′獲取房屋樓層數(shù) Exit For′符合條件后,退出循環(huán) ElseIf Srtxt.Length=1 Then House_jg=Srtxt End If:End If:End If:End If Next If House_jg IsNot Nothing Then′向?qū)嶓w添加擴展數(shù)據(jù) Dim dataTy(3) As Short, datatx(3) As Object dataTy(0)=1001: datatx(0)="TDGIS" dataTy(1)=1000: datatx(1)=Keywd_bm(Array.IndexOf(Keywd_jg, House_jg)) dataTy(2)=1000: datatx(2)=House_jg dataTy(3)=1040: datatx(3)=House_lc objline.SetXData(dataTy, datatx) End If objline.Update()′保存多段線的修改 Next End Sub 分別按照圖3、圖4、圖5在AutoCAD中繪制房屋并注記文字,程序運行后,使用CAD擴展命令XDLIST查看各房屋的擴展數(shù)據(jù)內(nèi)容如下,結(jié)果如圖6所示。 圖6 * Registered Application Name: TDGIS * Code 1000, ASCII string: 141161 * Code 1000, ASCII string: 混 * Code 1040, Real number: 2.0000 上述程序設計合理、邏輯緊湊,限于篇幅程序中略去了啟動CAD的代碼。用較簡短的代碼將多種不同的注記樣式統(tǒng)一處理,具有較強的通用性和實用性。在當前的農(nóng)村集體土地使用權(quán)確權(quán)項目中,僅需要在房屋內(nèi)部注記表示結(jié)構(gòu)和樓層的文字,就可以通過程序自動掛接屬性,不僅解決了無屬性房屋難處理, 房屋注記與房屋擴展數(shù)據(jù)不一致等一系 列難題,而且避免了手工掛接房屋擴展數(shù)據(jù)的重復浪費,在實際作業(yè)中針對不同的GIS入庫要求,通過二次開發(fā)很容易實現(xiàn)用戶的特殊要求,顯著提高了生產(chǎn)效率。 [1] 曹祖圣,蔡文龍,林義證.Visual Basic 2005[M].北京:科學出版社,2007. [2] 張帆,鄭立楷,盧擇臨,等.AutoCAD VBA二次開發(fā)教程[M].北京:清華大學出版社,2006. [3] 張曜,張青,李丁.Visual Basic函數(shù)實用手冊[M].北京:冶金工業(yè)出版社,2002. [4] 曾洪飛.AutoCADVBA&VB.NET開發(fā)基礎(chǔ)與實例教程[M].北京:中國電力出版社,2013. [5] 中華人民共和國國家質(zhì)量監(jiān)督檢驗檢疫總局. 1∶500 1∶1000 1∶2000地形圖圖式:GB/T 20257.1—2007[S].北京:中國標準出版社,2008. [6] 中華人民共和國住房和城鄉(xiāng)建設部. 城市測量規(guī)范:GJJ/T 8—2011[S].北京:中國建筑工業(yè)出版社,2012. [7] 洪濤,譚仁春,李寧.AutoCAD數(shù)據(jù)自動創(chuàng)建ArcGIS“地圖瓦片”服務的方法研究[J].測繪通報,2015(12): 85-87. [8] 劉仁峰,吳志春.AutoCAD平臺下DLG建庫的關(guān)鍵技術(shù)研究[J].測繪通報,2015(9):113-116. [9] 河南省國土資源廳.河南省農(nóng)村集體土地使用權(quán)確權(quán)登記發(fā)證實施細則(試行)[EB/OL].[2016-04-10].wenku.baidu.com. Research of Method Based on VB.NET House Extension Data Automatic Articulated LIU Xuejie,ZHANG Fuli 2016-06-21 劉學杰(1968—),男,高級工程師,主要從事工程測量方面的工作。E-mail:zwchlxj@126.com 劉學杰,張福利.基于VB.NET的房屋擴展數(shù)據(jù)自動掛接方法[J].測繪通報,2016(12):111-115. 10.13474/j.cnki.11-2246.2016.0414. P208 B 0494-0911(2016)12-0111-05三、程序?qū)崿F(xiàn)的過程分析
四、程序運行及實踐應用