沈暉
(第七一五研究所,杭州,310023)
電子海圖不管是在軍用還是民用都具有很重要的應用價值[1],它相比普通的態(tài)勢圖具有更加直觀、更加形象等特點[2]。電子海圖插件版本眾多,所應用的平臺也各不相同,本文應用的YimaEnc電子海圖的版本號為YimaEnc3.9.8,是YimaSoft公司使用Yimap Core開發(fā)的應用于電子海圖領域的系列軟件。YimaEnc電子海圖符合國際海事組織(IHO)制定的數據標準S57和顯示標準S52[3],具有較好的刷新顯示效率和海圖動態(tài)加載速度。
YimaEnc電子海圖引擎內核基于標準C++開發(fā),具有良好的跨平臺性能[4],支持Windows、Android、IOS、WinCE、Linux、VxWorks等[5]。本文是 Windows系統(tǒng)下YimaEnc在Winform開發(fā)框架中的應用,利用YimaEnc電子海圖進行二次開發(fā)、創(chuàng)建自定義的開發(fā)接口,按項目需求開發(fā)出自定義的支持S57和S52標準的電子海圖系統(tǒng)。鑒于YimaEnc電子海圖的優(yōu)點,以及時下對程序設計的用戶界面需求逐漸增強,所以將電子海圖應用在態(tài)勢圖程序中會有較好的效果。
YimaEnc組件包括核心控件 YimaEnc.ocx及“S57Lib”目錄下的7個庫文件。
(1)S57ObjectClasses是所有 S57的物標類(Object Class,在YimaEnc中稱為圖層-Layer)的定義,包括每個類別的名稱、縮略語和所包含的特征屬性列表;
(2)S57Attributes是所有S57的物標特征屬性的定義,包括每個屬性的名稱、縮略語、數據類型和枚舉或列表類型的各項枚舉值;
(3)S57Colours是所有S52定義的5中顏色模式列表,包括DAY_BRIGHT、DAY_WHITEBACK、DAY_BLACKBACK、DUSK、NIGHT五種模式下的所有顏色的縮略語、視覺顏色、CIE3分量、RGB3分量值;
(4)S57Symbols是所有S52的點物標符號定義;
(5)S57ComplexLineStyles是所有S52的線物標循環(huán)符號定義;
(6)S57Patterns是所有 S52的面物標填充符號定義;
(7)S57LookupTable是所有S52的物標對象顯示風格規(guī)則定義。
YimaEnc電子海圖組件對象內有一個海圖管家,它負責所有的海圖管理和顯示任務,包括一個海圖庫、一個內存海圖序列、一個海圖繪制器及多個海圖屏幕窗口。YimaEnc電子海圖軟件結構如圖1所示。通過調用海圖管家的操作接口函數,可以實現以下6個功能:海圖庫管理和內存海圖序列的管理功能;海圖繪制器的管理;海圖顯示控制;坐標轉換與地理計算;S52顯示全局參數控制;海圖物標查詢和高亮功能。
首先需要注冊 YimaEnc.ocx成功,由于該YimaEnc電子海圖版本只支持x86的Windows系統(tǒng),所以在創(chuàng)建Winform項目的時候,需要將項目生成的目標環(huán)境改為 x86。該版本海圖插件所有的接口用法在“YIMAENC SDK 開發(fā)文檔.chm”中有詳細的解釋說明,以下就最基本的接口和最常用到的接口進行詳細解釋說明。
圖1 YimaEnc電子海圖軟件結構
在程序需要顯示海圖的時候加載以下3個接口函數:Boolean Init(String strWorkDir);Boolean RefreshDrawer(Int32 hwnd, Int32 scrnWidth, Int32 scrnHeight, Int32 scrnOrgOffsetPoX, Int32 scrnOrgOffsetPoY);Boolean DrawMapInScreen(Int32 hdc)。
項目啟動時,要完成兩個重要的初始化工作:海圖組件的初始化(Init接口),海圖繪制器的初始化(RefreshDrawer接口);然后,在響應目標窗口繪畫消息的時候(例如Form的Load事件或者Panel的Paint事件等)調用組件接口(DrawMapScreen),將海圖繪制到目標窗口上,即可實現海圖的顯示。
在開發(fā)過程中,通過鼠標操作以及鼠標事件響應,可以獲取鼠標當前的桌面坐標,經常需要將桌面坐標和海圖的地理坐標進行互相轉換,需要用到以下 2個接口函數:void GetGeoPoFromScrnPo(Int32 scrnPoX, Int32 scrnPoY, Int32* retGeoPoX,Int32* retGeoPoY);void GetScrnPoFromGeoPo(Int32 geoPoX, Int32 geoPoY, Int32* retScrnPoX, Int32*retScrnPoY)。
YimaEnc電子海圖中的物標主要分為本艦(OwnShip)、目標船(OtherVessel)、自定義物標(以“tm”開頭的接口函數添加的物標)。本艦有固定的圖層號(LayerPos)和物標號(InnerLayerObjPos);目標船有固定的圖層號而沒有固定的物標號;自定義物標沒有固定的圖層號和物標號。每次繪制或者設置海圖中某一物標時,本艦可直接進行繪制,目標船要提供物標號,自定義物標需要提供圖層號和物標號。通過以下2個接口可以獲取圖層號或者物標號:int GetOtherVesselPosofID(int vesselID);void tmGetObject PosFromID (int layerID, int innerLayerObjID, ref int retLayerPos, ref int retInnerLayerObjPos)。
經緯度坐標值為4 byte整型數,其數值為以度為單位的浮點數經緯度坐標值乘以一個固定的乘積因子(MultiFactor = 10 000 000)。
YimaEnc電子海圖中對象的索引為該對象在其序列中的位置,起始值都為0的整型數,分為一維和多維Pos。一維Pos中:libMapPos表示海圖在圖庫中的索引;memMapPos為內存海圖序列中某幅海圖的索引;layerPos是圖層索引;innerLayerObjPos為物標在圖層內部的位置;attrPos表示屬性位置。多維Pos中:MEM_GEO_OBJ_POS用于在整個內存海圖序列中唯一標識一個物標,包括3個子索引,即 memMapPos、layerPos、innerLayerObjPos;M_GEO_OBJ_POS用于在某一確定的海圖內唯一標識一個物標,包括 2個子索引,即 layerPos和innerLayerObjPos。
如2.3節(jié)所述的,繪制物標時都會自動生成相應的圖層號或物標號;而設置物標需要提供相應的圖層號或物標號。與Pos對應的是ID,即圖層或者物標的 ID編號,都是表示在當前海圖中所處的一個索引號,然而兩者有本質的區(qū)別。
在YimaEnc電子海圖中,ID表示各種對象(圖層或物標等),它是唯一、不可重用的。ID從1開始,在當前項目運行過程中,每添加個圖層或者物標,ID從1開始進行加1計數,若刪除一個圖層或者物標,該 ID不會被回收利用。所以進行設置各種對象時,通過2.3節(jié)的兩個接口,獲取相應的Pos后再繪制圖層或物標,否則會出現內存索引無法找到或者內存索引錯誤。Pos從0開始,與ID不同的是 Pos是回收再利用的,所以當刪除一個對象后,再重新設置對象時,該對象的Pos將會變化,此時需要通過2.3節(jié)列出的接口進行重新獲取當前對象的Pos。
YimaEnc電子海圖提供自定義編輯海圖的功能。接口庫中所有以“tm”開頭的接口函數都是用于自定義海圖,自定義海圖有兩個重點:Layers文件和SymbolEditor工具。Layers文件用于自定義海圖圖層,可編輯圖層類型(包括點、線、面)、圖層屬性、圖層樣式等。根據Layers文件中的圖層順序,訪問該圖層時從索引0開始。YimaEnc電子海圖提供了自定義符號庫的功能,使用SymbolEditor工具可以進行自定義編輯符號樣式(包括點、線、面),工具中的符號編號如3.3節(jié)所述的對象ID一樣,是不進行回收利用的,編輯完成需要進行符號庫的保存。SymbolEditor工具中的符號庫可以直接應用在 Layers文件中的圖層樣式設置中。通過Layers文件和SymbolEditor工具,實現了電子海圖顯示的多樣化。
可以根據實際的需求,在原YimaEnc海圖插件所提供的接口基礎上,進行二次自定義接口開發(fā)。根據實際項目需求,針對繪制跟蹤目標進行的二次接口開發(fā),開發(fā)需求為新增跟蹤目標點和更新已繪制的跟蹤目標點,結合3.3節(jié)所述的開發(fā)要點,編寫了若干個drawTrackNode重載的自定義接口函數:
(1)public int drawTrackNode(double track_lon,double track_lat, int layerPos, int batch, bool ifShowText = false) 功能為繪制跟蹤目標節(jié)點。通過提供的參數,可直接通過該接口在繪制的同時獲取物標索引,再通過海圖插件提供的tmGetObjectID FromPos接口獲取物標ID和圖層ID;返回值是物標索引;參數包括目標經度、目標緯度、圖層索引、目標批號、是否顯示文本。
(2)public int drawTrackNode(double track_lon,double track_lat, int layerPos, int batch, bool ifShowText = false, bool ifNewSymbol = false) 功能為繪制跟蹤目標節(jié)點。通過提供的參數,可直接通過該接口在繪制的同時獲取物標ID,再通過海圖插件提供的 tmGetObjectPosFromID接口獲取物標索引;返回值為物標ID;參數包括目標經度、目標緯度、圖層索引、目標批號、是否顯示文本、是否設置新的符號標識。
(3)public int drawTrackNode(double track_lon,double track_lat, int layerPos, int batch, ref int layerID,bool ifShowText = false) 功能為繪制跟蹤目標節(jié)點。通過提供的參數,可直接通過該接口在繪制的同時獲取物標 ID,再通過海圖插件提供的tmGetObjectPosFromID接口獲取物標索引;返回值是物標ID;參數包括目標經度、目標緯度、圖層索引、目標批號、圖層ID的引用、是否顯示文本。
(4)public void drawTrackNode(double track_lon, double track_lat, int layerPos, int innerLayer ObjPos, int batch, bool ifShowText = false) 功能為更新原有的目標信息;無返回值;參數包括目標經度、目標緯度、圖層索引、物標索引、目標批號、是否顯示文本。
針對此類的開發(fā)需求,可以對所有點、線、面的海圖物標使用類似的自定義接口開發(fā)方法,即在繪制的同時返回物標的索引和物標的ID,而無需每次調用獲取Pos或ID的函數,從而降低代碼的冗余性。除了添加和更新物標,查看和刪除物標也同樣適用,由于添加和刪除的操作會將Pos值進行重新分配而 ID值不變,所以可使用添加物標時所記錄下的ID值進行當前Pos值的獲取,繼而直接使用Pos值進行物標的查看和刪除。
通過使用 YimaEnc電子海圖接口庫和在其基礎上自定義的接口庫,實際使用具有較好的便利性,對軟件的UI帶來了較好的體現,提高了用戶體驗。由于該YimaEnc電子海圖版本較老,雖可以滿足基本的需求,然而若需要獲得更加真實、實際的效果,還需要將電子海圖進行更新。本課題后續(xù)也會對該版本的電子海圖在此基礎上進行三維化的研究[6],使得顯示效果更加貼近實際。
[1]姜均. 基于YIMAENC的電子海圖的制作方法[J]. 電腦編程技巧與維護, 2015, (20):77-78.
[2]張振華,王遠斌,葉玲.基于 S-57標準的電子海圖的設計與實現[J]. 艦船電子工程, 2015, (2):94-98.
[3]鄭堯.電子海圖與雷達圖像的融合顯示[J]. 艦船科學技術,2015, 37(2):181-184.
[4]翁躍宗, 孫騰達. 基于電子海圖的船舶定線輔助系統(tǒng)軟件的實現[J]. 中國航海, 2004, (03):8-11.
[5]李超, 潘明陽. 基于Android的電子海圖顯示系統(tǒng)研究與實現[J].大連海事大學學報, 2013,39(4):55-58.
[6]扈震,楊之江. 基于 S-57標準的電子海圖三維可視化[J].地球科學-中國地質大學學報, 2010,35(3):471-474.