一、前言
眾所周知,二維GIS技術發展了近四十年,伴隨着計算機軟硬件以及關系型數據庫的飛速發展,二維GIS技術已日臻完善。在對地理信息的分析功能上有着無可比擬的優勢。一些宏觀的地理信息,一維的地理信息,如河流、公路等,以及二維的地理信息,如植被、湖泊、人口數量等,在對這些地理信息的分析和處理上,比較適合采用二維GIS系統。二維GIS始於20世紀60年代的機助制圖,今天它已經深入社會的各行各業,如土地管理、電力、電信、水利、消防、交通、規划等,但二維GIS有其自身難以克服的缺陷,它本質上是基於抽象符號的系統,不能真實的再現三維客觀世界。隨着信息技術的快速發展特別是數字地球(Digital Earth)的提出與實施,以及GIS應用深度和廣度的不斷擴大,二維GIS已經無法滿足用戶的需求,用戶對三維GIS的需求愈發迫切。伴隨着計算機顯示設備以及存儲設備的進步,三維GIS也得到了一定的發展,GIS正在經歷一個由二維向三維發展的過程。
三維GIS最大優點是可以真實的再現現實環境中的地理信息,如地形、地貌等。利用三維GIS技術和DEM、紋理數據可以實現真實感地形地貌的生成功能,以及實時漫游功能等,對於一些只有三維GIS技術才能實現的功能,也必須由三維GIS技術實現,如為了更加直觀地理解空間查詢和分析的結果、提高空間分析的水平,有必要恢復三維空間關系,並進行透視顯示。但是三維GIS才起步不久,並沒有成熟的空間數據模型給予其強有力的支撐,空間數據庫也並不能完全表達空間實體的復雜關系。三維GIS的核心即是地形三維可視化及其查詢分析,地形三維可視化技術自20世紀90年代以來一直是地理信息系統領域開發和應用的熱點方向之一,地形三維可視化是一門利用數字化高程模型(DEM)顯示仿真內容的學科,是圖形學研究方向的熱門課題,而DEM數據的三維顯示是地形三維可視化的基礎。近年來,地形三維可視化技術越來越廣泛地運用於地理信息系統、防洪決策系統、虛擬環境仿真、國土資源管理等領域。隨着科學技術的發展,地形三維可視化逐漸成為當前對河道、湖泊和港口等進行防洪預測、河床演變分析研究的前沿及主要手段,同時也是快速、及時再現地形三維信息及分析的有效手段。現有的三維GIS系統中,系統功能在三維場景可視化、實時漫游等方面取得了較好的成果,但查詢分析功能比較弱。然而查詢分析功能在三維GIS的實現和應用中具有十分重要的地位,它使三維GIS具有輔助決策支持能力。
綜合考慮上述情況及因素,作者認為目前應以開發二維為主、三維為輔的混合型GIS為主要目標,不宜單純開發三維GIS。在當前GIS產業界,二維GIS已經能夠滿足大部分實際需求,對三維GIS的需求仍然只占少部分。當前三維GIS在三維數據獲取、大數據量處理與存儲、三維可視化、三維空間分析方面還不能以較好的性價比滿足大規模商業應用的需要。如果完全采用三維GIS,勢必將花費高昂的系統建設費用,在二維GIS能夠滿足需要的情況下,用戶沒有必要去一味追求高性能。當然,這里並不排除部分單位研制完全的三維GIS以滿足一些行業的特定需要,如軍事、采礦、石油勘探、地質結構研究等工作。所以發揮二維GIS與三維GIS的優勢,進行矢量數據與地形三維可視化的結合性研究有很大的實用價值。如果采用三維可視化的方法集成矢量數據,並實現其相關屬性的查詢分析,將二維GIS的優勢用在地形三維可視化中,使二維GIS與三維GIS得到良好的結合,對軍事、民航、氣象等行業有非常重要的現實意義。
目前不同的應用目的往往需要二維GIS與三維GIS兩種方式交替運作,而不是單一的某一種。因此,結合二維GIS與三維GIS於一體,充分發揮兩者的優勢,是一個即經濟又實用的思想,這也正是本研究的宗旨所在。所以研發一個使矢量數據與地形三維可視化集成的系統,具有重要的現實意義,本研究系統將分為二維和三維兩個部分,二維部分采用MFC與ArcGIS Engine實現,三維部分則采用ATL與OpenGL設計成ActiveX控件,ActiveX控件的集成性非常好,可以發布到任何聯網的用戶終端使用。因此,本論文將三維部分集成到二維部分中,使二維視圖與三維視圖形成一體化系統,采用的方式是動態加載ActiveX控件,該方式非常靈活,當ActiveX控件版本變化時,不必手動的更新。當然,不能簡單的堆砌為一個集二維GIS與三維GIS於一身的顯示系統,更重要的是使二維與三維兩個部分得以互動,所以,本論文將二維與三維有機的結合,實現了二維與三維的互動。下圖說明了本系統的總體設計思路。
本系統是由二維與三維兩個部分共同構建的,如下圖所示的系統主界面。系統分為左右兩個視圖,左視圖是二維部分,右視圖是三維部分,下面將詳細闡述二維部分、三維部分以及二維與三維互動的設計與實現,並用某地數據進行了測試。
二、技術路線和功能簡介
1、二維部分
本系統二維部分使用VC提供的MFC與ArcGIS Engine組件實現。在MFC中使用ArcGIS Engine的控件、接口和方法必須遵循一定的步驟,並不像VB、DoNet中那樣方便,下面詳細介紹在MFC中應用ArcGIS Engine的步驟。
1、引入ArcGIS Engine控件庫文件(*.ocx)和組件庫文件(*.olb)。控件庫中定義了與控件相關的接口,組件庫中定義了與控件無關的接口。引用語句如下,其中除庫文件名(如:esriGeometry.olb)外其余各參數均采用默認即可;
#import <esriGeometry.olb>_ //庫文件名
raw_interfaces_only_
raw_native_types_
no_namespace_
named_guids_
exclude("OLE_COLOR", "OLE_HANDLE")
2、加載ArcGIS Engine控件。VC控件工具箱中有一些默認加載的控件,這些控件可以在對話框中進行所見即所得的繪制,但ArcGIS Engine控件並沒有加載進去,因此需要手動加載,使得可以在對話框中繪制Map、Scene、Toorbal等控件,VC中提供了兩種加載控件的方法;
第一種本論文稱之為COM方式,該方式加載的控件圖標並不出現在工具箱中。首先右擊對話框,選擇“插入ActiveX控件”;然后選擇“插入ActiveX控件”對話框中要加載的控件,如:ESRI MapControl,這樣MapControl即出現在對話框中。
第二種本論文稱之為C++方式,該方式加載的控件圖標出現在工具箱中,並且向VC工程中添加該控件的VC源文件(*.cpp)和頭文件(*.h)。首先,選擇工程->增加到工程->Components and Controls菜單,打開“Components and Controls”對話框,選擇Registered ActiveX Controls中要插入到工程的控件,如:ESRI MapControl,這樣MapControl即出現在VC工具箱中,便可以像默認控件那樣,在對話框中繪制MapControl。
3、定義ArcGIS Engine的類對象。ArcGIS Engine包含三種類[62]:抽象類(abstract class)、可實例化類(class)和組件類(cocalss)。抽象類不能用以創建新對象,但可以指定子類;可實例化類不能夠直接創建新對象,因為它的構造函數是私有的,但可以通過其他類對象的屬性或其他類的方法實例化;組件類指的是能夠直接使用通過開發環境中的對象定義語法來創建對象的類,組件類可以直接被創建或者實例化。
VC中均采用智能指針來聲明ArcGIS Engine接口,可以被實例化的類在VC中具有三種實例化方式:
第一種本論文稱之為類標識方式。在類對象聲明時,直接使用類唯一標識(CLSID)進行構造,如:IFieldsPtr pFlds(CLSID_Fields);
第二種本論文稱之為ATL方式。在類對象聲明時,使用CocreateInstance方法進行構造,如:CComPtr<IFields> pFlds;pFlds.CoCreateInstance(CLSID_Fields);
第三種本論文稱之為COM方式。在類對象聲明時,使用CreateInstance方法進行構造,如:IFeatureLayerPtr pFlds;HRESULT hr = pFlds.CreateInstance(CLSID_Fields)。
經過以上步驟,即可以應用ArcGIS Engine提供的接口、方法進行本系統二維部分的程序設計。二維的功能如下圖所示,其中數據轉換部分實現了由Shapefile向TIN及Raster的轉換和由TIN或Raster生成等高線。二維AE部分實現了DEM及SHP文件的顯示,以及對DEM分層設色、生成坡度、通視分析、TIN的三維顯示、誇張系數設置等功能。
下面是二維的一些貼圖。
2、三維部分
本系統三維部分使用VC提供的ATL與OpenGL實現。ATL是活動模板庫(Active Template Library)的簡稱,是VC中為了支持COM而提供的輕便類庫,用ATL可以容易的定制COM組件,並不需要自己寫模塊定義文件(*.def)。在ATL中使用OpenGL的步驟如下。
1、引入OpenGL函數庫。首先,選擇工具->選項菜單,分別選擇目錄->Include files和目錄->Library files,將相應目錄添加進去;然后,在stdafx.h文件中加入如下語句,引入OpenGL頭文件和庫文件(*.lib)。
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glaux.lib")
#include <gl"gl.h>
#include <gl"glu.h>
#include <gl"glaux.h>
2、在具體的實現過程中,由於OpenGL函數通過“繪制場景”(Rendring ContextRC)完成三維圖形的繪制。Windows下的窗口和設備場景支持位圖格式屬性,該屬性與RC存在位圖結構上的一致。只要在創建RC時將它與一個DC(Device Context)相關聯(RC只能由一個已經建立了位圖格式的DC來創建),OpenGL的函數就可以通過RC對應的DC繪制到相應的顯示設備上,相應的步驟如下:
1)設置顯示設備DC的位圖格式屬性。通過填寫一個PIXELFORMATDESCRIPTOR的結構來完成,該結構決定了OpenGL繪圖的物理設備屬性,另外,DC有可能只支持部分位圖格式,因此首先使用函數ChoosePixelFormat選擇與DC支持的指定位圖格式最接近的位圖格式,然后使用函數SetPixelFormt設置DC的位圖格式。
2)創建繪制環境RC與DC的聯系,利用DC創建繪制場景RC(wglCreateContext),以便在DC與RC之間創建關聯,此時需要使用函數wglMakeContexte。
3)調用OpenGL函數進行繪制。
4)釋放相關內存。繪圖完備后,需要調用函數wglMakeContext設置當前線程的RC為NULL,從而斷開當前線程和該RC的關聯,並由此斷開與DC的關聯。
一般地,在使用單個RC的應用程序中,相應的WM_CREATE消息時創建RC,當WM_CLOSE或WM_DESTROY到來時再刪除它。在使用OpenGL命令往窗口中繪制圖形之前,必須先建立一個RC,並使之成為現行RC。OpenGL命令無需提供RC,OpenGL將簡單地忽略所有的繪圖命令。
經過以上步驟,即可以應用ATL及OpenGL從底層實現本系統三維部分的程序設計。三維OpenGL部分的功能如下圖所示,三維部分采用Roam算法實現DEM的三維可視化以及紋理的疊加,並實現了在三維場景中的實時漫游和Shapefile疊加到紋理表面,可以清晰的看到Shapefile疊加到紋理表面后的是有起伏的,這是因為Shapefile是繪制在紋理圖像上的,避免了低於地形或高於地形的情況,為有關部門的規划管理提供了支持。
下面是一些三維貼圖。
1、疊加shapefile的效果圖
2、漫游瀏覽的效果圖(不知為何變成黑白色了,暈)
3、Roam算法生成的Dem格網圖
三、二維與三維集成及互動1三維ActiveX控件集成到二維部分
欲將ActiveX控件集成到二維部分,首先必須將二維部分分割成左右兩個視圖,然后將ActiveX控件插入到其中一個視圖中,詳細實現如下。
1、分割MFC視圖(View)。首先建立一個繼承自CFormView的視圖COpenGL,該視圖即是三維ActiveX控件的載體;然后建立一個繼承自CSplitterWnd的類CMySplitter,該類用來創建左右兩個視圖;最后重載CMainFrame的OnCreateClient函數,在該函數中調用CSplitterWnd的CreateStatic函數創建兩個視圖,並用RUNTIME_CLASS將COpenGL作為其中一個視圖顯示。
2、動態加載ActiveX控件。首先如上節的方法插入三維ActiveX控件;然后在COpenGL類的OnCreate函數中使用CWnd類的CreateControl動態的加載ActiveX控件。
2 二維與三維互通信
二維視圖與三維視圖的互通信是實現二維與三維的互動的基礎,二維與三維互通信分為以下兩步。
1、視圖間互通信。它不是簡單的函數調用問題,因為MFC的默認視圖類(CView)並不能安全的與除文檔類(CDocument)以外的其余視圖類進行通信,所以,必須使得所有視圖類均先與文檔類進行通信,這就需要重載CDocument::OnOpenDocument函數,將COpenGL類的指針加入其中即可以實現視圖間的通信。
2、MFC視圖與ActiveX控件通信。ActiveX控件所提供的方法均沒有返回值,而實現MFC視圖與ActiveX控件的通信又必須得到方法的返回值,解決這個矛盾有三種方法:
一是將方法的參數設置為指針類型;
二是提供相應方法的屬性,在屬性內部調用ActiveX的類函數;
三是將方法聲明成事件,並可以與默認的ActiveX事件掛鈎。
這三種方法各有千秋,需要結合應用,如:坡度坡向計算時,需要得到該點的坡度坡向兩個數值,即可將該方法的參數聲明為指針類型;距離量算時,只需得到距離一個參數值,即可將其聲明為屬性;坐標查詢時,需要在MFC視圖中截獲鼠標單擊的消息,因此要將該方法聲明為響應鼠標單擊的事件。
添加ActiveX事件是一項非常困難的工作,需要用接口定義語言—IDL(Interface Definition Language)手動編寫接口定義文件(*.idl)。下面以添加鼠標單擊事件Click為例說明添加事件的步驟。首先,應用guidgen.exe獲得一個唯一標識碼作為Click事件的接口_IEvent的ID,然后將_IEvent聲明為[default, source]dispinterface,編譯idl文件,並添加該_IEvent的Click事件的連接點(Connection Point),系統會自動產生一個繼承自IConnectionPointImpl接口的CProxy_IEvents類,並在該類中加入Fire_Click方法,該方法即為Click事件。這樣只是添加了Click事件,還必須將其與ActiveX默認的鼠標單擊事件OnLButtonDown掛接,才能響應鼠標單擊的消息,因此必須在OnLButtonDown中調用Fire_Click方法,一切處理均在OnLButtonDown中實現,而后傳入Fire_Click中。
3 設計思路
本研究的核心思想即是有機的結合二維GIS與三維GIS,並將兩者統一應用到一個系統中,使在三維中難以實現或算法復雜的功能應用二維GIS實現,而在二維中不能實現或不夠精確的功能應用三維GIS實現,使二維GIS與三維GIS優勢互補。
本文即應用該思想設計一個二維與三維結合的系統,在本系統中,要達到矢量數據和三維場景之間的一一映射,必須建立兩者之間坐標系的唯一對應或對應地理目標名稱[63](唯一的ID)的一一對應,一旦獲得對象的唯一標識,就可以獲得對象實體的全部信息。本論文選擇坐標對應方式,獲得三場景中任意一點對應的地面點坐標是進行有關空間信息的查詢操作和地形分析的前提,因此在三維部分中最為重要的就是如何獲得三維坐標,對點的空間位置查詢是其余地形空間信息查詢的基礎,本論文改進了現有的三維坐標查詢算法(見3.3.4節),使查詢三維坐標更加方便准確。通過建立二維與三維兩部分坐標的對應和消息響應機制可以實現矢量數據與三維場景的互動。如:
1、用戶在三維場景中漫游時,在二維場景中顯示出相應的位置和視野(FOV);
2、在二維場景中改變觀察者位置的時候,相應地在三維場景中跳到對應的位置。在三維場景中改變觀察者的位置,在二維場景中視點也跳到對應的位置;
3、二維中進行目標屬性信息查詢的時候,三維場景的對應目標高亮度顯示;
4、三維中進行目標屬性信息查詢的時候,二維場景的對應目標高亮度顯示;
5、由於二維GIS宏觀性、整體性、簡潔性的特點,在二維中實現剖面圖繪制、通視分析、坡度圖繪制等宏觀的功能;
6、由於三維GIS局部性、現實性、直觀性的特點,在三維中實現地形的真實再現、面積量算、距離量算、單點坡度坡向計算等微觀功能;
二維GIS與三維GIS結合應用,即克服了二維GIS的抽象多義性,又避免了三維場景漫游的方向迷失感。本研究充分發揮了兩者的優勢,通過二維GIS與三維GIS的互動實現GIS功能,而不局限於用單一的方式來實現,這樣即增強了系統的靈活性,又使問題簡單化。
4 功能介紹
經過以上兩步,二維與三維互動的准備工作已經完成,二維與三維互動的根本思想即是通過二維與三維的互通信,使得二維與三維互相關聯,形成一個有機的整體。實現了二維與三維的互動的功能。其中坐標查詢是最為關鍵的功能,是實現其他功能的基礎與前提。下面詳細說明這些功能實現的主要思想。
4.1、坐標查詢。二維中只具有 坐標,三維中具有 坐標,因此欲得到二維中鼠標點擊位置的三維坐標,必須將二維中的 傳入三維中,經過改進算法的計算即可;而三維中坐標與二維中對應只需將三維中的 坐標傳入二維中。這樣就實現了二維與三維互動的坐標查詢功能,如下圖所示,經驗證獲得的坐標正確,且實現了二維與三維的坐標對應。
4.2、場景定位。在二維中想了解某個位置的詳細情況時,可以直接將二維坐標傳入三維中,計算出三維坐標后,在進行局部放大到相應位置的三維視圖。如果想獲得二維中某條線路或某個區域的具體信息,可以將該線路或區域傳入三維中繪制在地形紋理上進行仔細觀察,其中區域繪制有透明和非透明兩種,透明采用遍歷活性邊表的掃描線算法進行填充,非透明采用GDI的FillRgn函數進行填充;而三維中漫游時,如果迷失方向,則可以將三維坐標傳入二維中進行定位標識,如下圖所示,二維中的任意位置、線路及區域均可在三維中作相應的繪制,均具備有地形相符的起伏;而三維中漫游時亦可隨時定位到二維中。
4.3、距離量算。如果在三維GIS中測量曲面距離,必須與網格線進行多次求交,得到相應的交點再計算,這樣勢必大大增加系統負擔,而二維GIS中恰好可以應用IPointCollection接口直接獲得與網格線的交點集合,但二維GIS中的距離是投影距離,而曲面距離中每一段距離是空間距離,所以,如果是三維中兩點的曲面距離,首先需將起終點傳入二維GIS中,獲得與網格線的交點集合再傳回三維GIS中進行計算即可;而如果是二維中兩點間的曲面距離,即可首先得到交點(x,y)坐標集合,然后傳入三維中,獲得網格點集合的(x,y,z)坐標,再進行計算即可。下圖即為按照該方法得到的投影、直線、曲面三種距離。
還有體積、剖面圖、三維二維加載shapefile等功能,此處就不再一一贅述。完結啦,^_^