王光昇,周麗珠,劉允,周義軍
(天津市測繪院,天津 300381)
在過去的十年中,基于AutoCAD的地形圖成圖軟件在我們國內制圖,設計領域一直占據著主導地位,這主要是因為AutoCAD軟件在表現線劃圖形上方便易用以及Autodesk的品牌效應。但從根本上來講,Autodesk的一系列產品中,并沒有多少功能是專門為我們測繪行業設計的,所以AutoCAD軟件自然也不是為測繪行業量身定做的。但是傳統的測繪成圖軟件,如廣州開思、南方開思軟件通過“堆砌”的方式將CAD原生要素,如文本、點、線等拼湊成地形要素的模樣,從圖面上來說,達到了表現地形的目的。這種成圖方式在從手工制圖向數字化成圖轉變過程中起到了不可替代的作用。然而在信息化測繪的今天,它的弊端就顯現出來了,數據冗余、圖形零散、編輯困難等。可以說,在這種成圖方式中,過于注重圖面表示,沒有突出“信息”的作用。我們必須調整數據采集及成圖方式以適應信息化測繪要求。AutoCAD的ObjectARX開發工具為我們提供了自定義實體技術,它可以幫助我們定制自己的地形圖要素,極大地優化數據組織結構,提高數據應用效率。由于自定義實體可以用程序控制要素的外觀顯示,所以,就可以根據不同的用戶信息動態表達出不同的外觀圖形,這更貼近信息化測繪的需要。
下面結合實例來分析一下定制自定義實體的基本思路。
我們自定義了一個符號對象MYSYMBOL,可以用來表現控制點,如圖1所示。

圖1 自定義符號類
(1)通用性
設計的自定義對象,一般用來表示一大類要素,而不是某一個具體的要素。當然對于某些特殊的要素要定義專門的自定義對象。如圖1所示的控制點對象,對象的名字為MYSYMBOL,之所以命名為Symbol,是因為我們想讓這個對象能盡可能地表現所有點狀要素,如高程點、獨立符號等,如表1所示。

自定義對象的通用性 表1
表1中表現的符號并不是固定不變的,所用的符號樣式也是與編碼一一對應的。這種對應關系由外部配置文件進行管理。
(2)編碼驅動
一般我們都是以編碼來標識地物要素的,這一點沒有任何疑義,但是傳統成圖軟件是借用CAD內部對象的thickness屬性來存儲編碼。為什么用它呢,因為它基本上是唯一可以在屬性面板中修改而不影響二維平面圖形顯示的。但是thickness實際上是代表要素在三維空間中的厚度,如果我們把二維圖形切換到三維坐標系下,就可以看到thickness帶來的影響了,所以用它存儲編碼顯然是不合適的。而對于塊符號對象根本是沒有thickness的,我們還需要通過符號名稱把編碼與地物聯系起來,邏輯關系復雜化了。
所以我們在自定義對象時,我們為每個自定義對象都添加一項字符串類型的編碼屬性(Code),就可以做到編碼與要素一一對應,而且字符串類型值不會產生類似Thickness的雙精度損失問題。
(3)屬性狀態控制
在考慮自定義對象的通用性的同時,還要符合用戶的實際應用。表現高程點時,在屬性面板中就不應該顯示“樣式”屬性,即對于不同的對象要顯示不同的屬性項,如圖2所示。

圖2 自定義對象屬性狀態控制
(4)開放性
自定義的對象與一般的AutoCAD對象工作原理是相同。為了提高由自定義對象數據的使用效率,應該為用戶提供編輯接口,使得用戶可以用程序批量處理數據。
如圖1、圖2所示,編碼屬性是禁用的,因為不允許用戶隨意修改它,但是用戶可以通過程序修改編碼。
一般創建自定義實體的過程為:
(1)創建DBX工程和ARX工程。DBX工程用來管理自定義實體類,負責自定義實體的讀、寫、顯示等操作;ARX工程包含了程序入口點,在ARX命令函數中創建自定義實體對象實例,并可以在AutoCAD中加載運行。
(2)在“項目依賴項”中設置ARX工程依賴于DBX工程;
(3)如果想使自定義實體支持ActiveX自動化功能,還要為DBX工程添加ATL COM Wrapper對象;
(4)如果想在屬性面板中顯示自定義的屬性,必須在自定義實體類中實現subGetClassID函數,然后在新生成的*_i.c頭文件中復制CLSID并將其賦值給subGetClassID函數的參數*pClsid,如:

由DBX工程生成的自定義實體不能在AutoCAD環境中獨立運行,需要由ARX應用程序創建實例對象并添加到CAD數據庫中;而COM Wrapper對象對自定義對象進行二次封裝,為用戶提供編程接口。這樣用戶就可以很方便地訪問自定義對象的屬性和方法了。在CAD環境中,用戶通過屬性面板修改圖形屬性的操作,都是借助于COM Wrapper這個中間媒介來訪問自定義對象的;而有些操作,如拖拽夾點、平移、縮放等,則是直接訪問自定義對象,如圖3所示。

圖3 自定義對象工作流程
我們在ini文件中存儲每個要素的配置信息,如:

為自定義對象類添加TCHAR*類型的成員變量mCode,該變量用來標識要素編碼;添加用于表示符號位置的 AcGePoint3d類型的成員變量 mCenter。在subWorldDraw函數中根據編碼從ini文件中讀取符號名稱,如高程點的符號名稱為SYM-DM-001,然后繪制符號:

其他成員變量根據圖形表現的需要添加,本例中的成員變量還包括:

理論上來講,AutoCAD內部實體能夠實現的功能,自定義實體都實現。例如,可以通過LISP/VBA等編程手段操作一般對象,那在自定義實體中如何實現呢?
(1)支持AutoLISP編程
我們經常使用entget函數查看修改對象的屬性,如用語名(entget(car(entsel)))查看圖1所示的控制點的數據表:
((-1.<圖元名:7ed03d38>)(0."MYSYMBOL")(330.<圖元名:7ed01cf8>)(5."7D7")(100."AcDbEntity")(67.0)(410."Model")(8."0")(62.1)(100."CMySymbol")(90 .1)(1 ."1110101000")(10 217.633 193.896 156.72)(11
219.597 193.931 156.72)(210 0.0 0.0 1.0)(2 ."張灣嶺")(340.<圖元名:7ed01c88>)(40.1.0)(90.1)(41.0.0)(42 .1.0)(211 1.0 0.0 0.0))
在數據表中,我們可以根據DXF組碼進行過濾選擇,如根據編碼進行選擇:
(ssget"x"(list(cons 1"1110101000")))
這樣就可以在AutoLISP中建立選擇集進行循環處理了。
要想在上述數據表中添加編碼、點名等成員變量信息,我們需要在自定義實體類的dxfInFields、dxfOut-Fields函數中讀取和寫入成員變量。
(2)支持VisualLISP編程
當我們對自定義對象的屬性和方法進行了COM封裝后,就可以通過VisualLISP操作自定義對象了。當然在應用VisualLISP函數前要先用vlax-ename->vla-object函數將實體名轉成對象。
要實現對自定義對象的COM封裝,需要以下幾步:
(1)首先要建立一個ATL對象類,該類要繼承幾個接口對象:IOPMPropertyExpander、IOPMPropertyExtensionImpl、IAcadEntityDispatchImpl;
(2)在IDL文件中編輯接口屬性和方法;
(3)在COM類中定義并實現接口屬性;
(4)在屬性映射表OPMPROP_MAP中添加自定義屬性入口;
(5)要改變屬性面板中文本框中的顯示名稱,需要在GetDisplayName(DISPID dispID,BSTR*pBstr)函數中對dispID的值為0x401的pBstr參數賦新值;
(6)屬性面板中要改變每個分類的名稱,需要在GetCategoryName函數中針對不同的PROPCAT參數值,修改BSTR參數的名稱;
(7)在Editable函數中控制屬性的可編輯性,在ShowProperty函數中控制屬性是否可見。
為了使自定義對象的屬性表達更加靈活,我們為自定義對象定義了兩類屬性,一類是靜態的,即前文提到的COM包裝類中的屬性,另一類是動態屬性,用來存儲與圖形本身無關的屬性,如圖4中的“符號屬性”所示。

圖4 動態屬性
COM包裝類中的屬性直接存儲到對象自身數據表中,而動態屬性我們存儲在對象擴展字典的擴展記錄中。這樣在查詢的時候,可以根據擴展記錄的關鍵字直接得到。如圖4所示,需要定義兩種用于生成動態屬性的類,一個是派生于IDynamicProperty接口的用于處理字符串數據類型的類;一個派生于IDynamicEnumProperty的用于處理枚舉類型的類。在處理枚舉類型動態屬性數據時,需要注意的是,OPM僅處理VT_I4類型的數據,即LONG類型,所以在GetPropValueData(LONG index,VARIANT*pValue)函數中,pValue必須賦值為LONG類型,如存儲當前ComboBox下拉列表的索引,或者存儲對象的ID等。
目前基于AutoCAD中的地形圖成圖軟件,只有基于自定義實體技術才能最大限度地保證要素的完整性、優化數據組織方式。盡管軟件開發的難度大、周期長,但是對于它的研究仍然具有重要的意義。
[1]宋延杭,王川,李永宣.ObjectARX實用指南[M].北京:人民郵電出版社,1999
[2]老大中,趙占強.AutoCAD 2000ARX二次開發實例精粹[M].北京:國防工業出版社,2001
[3]Charles McAuley.AutoCAD 2000ObjectARX編程指南[M].北京:機械工業出版社,2000
[4]張長勛.AutoCAD VisualLISP程序開發技術[M].北京:國防工業出版社,2005
[5]余承飛,方勇.AutoCAD 2000二次開發技術(Object-ARX)[M].北京:人民郵電出版社,1999
[6]Autodesk.ObjectARX開發指南.1999