摘 要:地理信息系統(tǒng)是空間信息系統(tǒng)的一種特定形式,本文通過介紹地理信息系統(tǒng)(GIS)、函數(shù)轉(zhuǎn)換、繪圖、封裝地圖等基本知識,詳細的分析了GIS的圖形繪制方法。
關(guān)鍵詞:地理信息系統(tǒng)(GIS);地圖繪制
地理信息系統(tǒng)(Geographic Information System或 Geo-Information system,GIS)稱為“地理學信息系統(tǒng)”,是空間信息系統(tǒng)的一種特定形式。需要在計算機硬、軟件系統(tǒng)的支持下,對整個或部分地球表層空間中的有關(guān)地理分布的數(shù)據(jù)進行采集、儲存、運算、分析、管理、描述、顯示的技術(shù)系統(tǒng)。
地理位置中的經(jīng)緯度坐標只能在地理信息中代表為某個地點、標志或方位,對于用戶理解和認識周邊信息有一定的局限;在通過相關(guān)技術(shù)獲取到位置之后,了解了所處的地理環(huán)境,通過查詢和分析環(huán)境信息,為用戶的活動提供信息支持與服務(wù),更注重用戶的需求,滿足用戶的各種體驗。
一、地圖是通過函數(shù)的調(diào)用繪制出來的
地圖的繪制是對函數(shù)的基本操作,即使用繪圖語句畫出來的。從基礎(chǔ)的底層地圖繪制,就是使用繪圖函數(shù)繪制點、線、面、標準、柵格等組合起來,就形成了一張地圖。
二、地圖繪制中的關(guān)鍵——坐標轉(zhuǎn)換
.NET提供了大量繪圖方法,基本上都是以Graphics類的函數(shù)形式提供,包括各類幾何形狀、圖像、文字的繪制,通過這些方法可以畫出各種圖形。但是圖形的繪制和坐標方位有著贊揚聯(lián)系,使我們繪制的地圖可以轉(zhuǎn)換為地圖元素,即地理坐標的經(jīng)緯度,需要解決坐標轉(zhuǎn)換問題。
首先了解一下轉(zhuǎn)換函數(shù):
///經(jīng)緯度
///
public Point WorldToScreen(PointF xy)
再一個,有時,還需要根據(jù)屏幕上點位置反算出它的經(jīng)緯度,如在需要顯示鼠標指針處的經(jīng)緯度,所以還需要這么一個函數(shù):
///屏幕坐標
///
public PointF ScreenToWorld(Point xy)
有了這兩個函數(shù),就可以將以經(jīng)緯度表示的地理坐標轉(zhuǎn)換為屏幕坐標,然后再屏幕繪圖了。
三、繪圖
有了坐標轉(zhuǎn)換類Coordinator,就可以用經(jīng)緯度數(shù)據(jù)來繪圖了,如得到了經(jīng)緯度坐標數(shù)據(jù),就可以將經(jīng)緯度數(shù)據(jù)轉(zhuǎn)換為屏幕坐標,然后用Graphics的方法來畫出來了,Graphics對象又從哪里來呢?可以從一個Image對象創(chuàng)建,也可以從一個控件的Paint事件中取得。
為了使用方便,F(xiàn)reeMicaps把符號繪制功能封裝到三個符號類中,以靜態(tài)方法提供。
.NET的繪圖是對GDI+的封裝,包括了對點、線、面等各種圖形元素的封裝,圖形圖像的繪制、坐標旋轉(zhuǎn),各種反走樣和平滑等功能,功能十分強大,利用它可以繪出各種圖形。
四、圖層
為了使繪圖過程便于管理,可將繪圖過程分為組,如可以將一張地圖的繪制分為:交通地圖、建筑地圖、管道地圖、區(qū)域地圖等幾個過程,每次繪圖好像就是在一張玻璃上繪制,疊加起來就形成了一張地圖,這里把每次繪圖過程形象地稱為一個圖層。地圖分層后,圖層可以增刪,每個圖層可以單獨進行隱藏、設(shè)置屬性等,更重要的是可以將利用面向?qū)ο蠹夹g(shù)把每個圖層當做一個對象進行管理。
對圖層進行抽象,需要調(diào)用圖層繪制方法(Render),圖層標題(LayerName)和用于表示數(shù)據(jù)源的字符串(DataSource)。用于表示繪圖樣式的設(shè)置的LayerStyle,加上一些輔助方法屬性,最終形成如下抽象圖層類(CustomLayer)。
FreeMicaps中,每種數(shù)據(jù)對應一種圖層類,為了使圖層類編寫方便,使用了設(shè)計模式中的模板方法,定義繪制流程,主程序在調(diào)用圖層的Render()方法時,會自動判斷是否已經(jīng)讀入數(shù)據(jù),根據(jù)需要分析數(shù)據(jù)繪圖。
對于同一種類型數(shù)據(jù),需要從CustomLayer繼承新建一個圖層類。各種類型數(shù)據(jù)圖層的工作方式一樣,僅在數(shù)據(jù)讀取和繪制方面不同。所以,寫新圖層類時,僅需實現(xiàn)DoLoad()和DoRender()兩個抽象方法,完成讀取數(shù)據(jù)和繪制圖層代碼即可。FreeMicaps里使用了字符串作為數(shù)據(jù)源標識,通用GIS系統(tǒng)對數(shù)據(jù)源進行了抽象。
一張地圖有多個圖層,所以還需要將圖層放入一個列表,用于繪制地圖時遍歷圖層。調(diào)用每個圖層的Render()方法,形成一張完整的地圖。
圖層繪制是需要有順序的,在圖層的樣式(LayerStyle)中放了一個ZOrder屬性,通過它來控制圖層順序。但由于List本身的排序方法是一種“非穩(wěn)固排序”,也就是說當兩個圖層的ZOrder相等時,它們的順序是不確定的,為了避免這個問題,F(xiàn)reeMicaps從CollectionBase繼承了一個類LayerList,實現(xiàn)對圖層的管理,并實現(xiàn)了IXmlSerializable接口,完成圖層序列化功能。
FreeMicaps中,每種數(shù)據(jù)對應一種圖層類,為了使圖層類編寫方便,使用了設(shè)計模式中的模板方法,定義繪制流程,主程序在調(diào)用圖層的Render()方法時,會自動判斷是否已經(jīng)讀入數(shù)據(jù),根據(jù)需要讀數(shù)據(jù)繪圖。
五、封裝地圖
有了坐標轉(zhuǎn)換類、圖層類、圖層列表類,就可以利用它們做出一個具有縮放平移、圖層管理等功能的地圖了,但為了更方便地對地圖進行操作,還需要對這些類進行組合封裝。
新建一個類WeatherMap,添加Coordinator和LayerList類的實例作為它的屬性,將Coordinator類的實例作為私有成員,將地圖坐標轉(zhuǎn)換等方法加入WeatherMap類,調(diào)用WeatherMap類的方法。
再回到抽象圖層類CustomLayer,它有一個成員Map,即為WeatherMap對象,在將圖層加入圖層列表時會自動賦值。在編寫CustomLayer的子類時,可調(diào)用它來進行坐標轉(zhuǎn)換和地圖操作。
為了使地圖在繪制復雜圖形過程中不至于BUG,需要在繪圖過程中能隨時中斷繪圖,如快速縮放平移地圖中,可終止前次繪圖過程直接繪制最后一次,就實現(xiàn)了地圖繪制的多線程,特別是多線程操作UI,對程序流程造成了一定混亂。
六、再次封裝-增加UI
上面已完成了地圖繪制的核心代碼,為了使代碼編寫更加容易,需要對WeatherMap類再次進行封裝(MapView類),加入UI部分,即給地圖加一個具有界面的殼,并在上面實現(xiàn)地圖的操作如縮放、拖動功能。
MapView從PictureBox類繼承,內(nèi)建了WeatherMap類的實例,在MapView的Refresh()方法中調(diào)用WeatherMap.Render()對地圖進行繪制。
為了完成對地圖的操作,F(xiàn)reeMicaps定義一個IMapTool接口,包含了鼠標和鍵盤操作方法,MapView類內(nèi)建一個IMapTool接口成員,MapView的鼠標和鍵盤操作,將被IMapTool接口的實例接管,在實現(xiàn)IMapTool接口的類中,可對地圖做各種操作,如平移、縮放等操作,這個對象可隨時替換以實現(xiàn)不同方式的地圖操作。
在FreeMicaps中,已完成一個實現(xiàn)IMapTool接口的類ZoomTool,此類為默認的地圖縮放和平移工具。
另外,在MapView中,還引入了一個當前圖層的概念CurrentLayer,用它來表示當前操作的圖層,后面用它來實現(xiàn)圖層元素拾取、圖層工具條等功能。
通過以上論述的方法,可以對地圖的開發(fā)有了全面、透徹的了解,便于開發(fā)人員對地圖系統(tǒng)的優(yōu)化和升級。文章對GIS系統(tǒng)的論述僅限于基礎(chǔ)應用和開發(fā),不妥之處請批評指正。
參考文獻:
[1] 朱洪軍.基于GIS的移動終端LBS系統(tǒng)建設(shè)與實現(xiàn)[D].華東師范大學,2008.
[2] 李海艷.移動GIS的概念體系研究[D].長安大學,2006.
作者簡介:
王盼(1985-),男,漢族,北京人,本科,工程師,單位:國家新聞出版廣電總局北京廣播電視維護中心,研究方向:廣電系統(tǒng)節(jié)目傳輸和調(diào)度。