趙軍,宮麗瑋,周圣川,胡振彪
(1.青島市勘察測(cè)繪研究院,山東 青島 266032; 2.青島市西海岸基礎(chǔ)地理信息中心有限公司,山東 青島 266000)
隨著智能移動(dòng)設(shè)備的飛速發(fā)展,電子海圖系統(tǒng)不再停滯于桌面系統(tǒng),移動(dòng)端電子海圖系統(tǒng)的應(yīng)用也越來(lái)越多。然而,相比傳統(tǒng)桌面電子海圖系統(tǒng),移動(dòng)設(shè)備由于其存儲(chǔ)空間小、運(yùn)算能力有限、屏幕尺寸較小、輸入輸出形式較少[1,2],對(duì)于大量TPK海圖柵格瓦片的加載,“瘦小”的移動(dòng)設(shè)備就顯得不切實(shí)際,對(duì)于數(shù)據(jù)的更新也是一個(gè)難題。其次,移動(dòng)設(shè)備可視化范圍較小,對(duì)于海圖符號(hào)的精細(xì)化顯示要求更高,這些相對(duì)傳統(tǒng)桌面海圖系統(tǒng)可以忽略的問(wèn)題,在移動(dòng)設(shè)備上都是必須解決的難題。
本文將矢量電子海圖“移植”到移動(dòng)端;同時(shí),不同于傳統(tǒng)的純底層電子海圖讀取-解析-顯示-功能開發(fā)模式,本文依托ArcGIS for Android SDK作為技術(shù)框架,通過(guò)繼承圖層類DynamicLayer,自定義新View圖層類,采用MVC模式,不僅實(shí)現(xiàn)了矢量電子海圖的可視化,采用ArcGIS本身的可視化引擎,可視化速度和效果顯著,而且“借用”ArcGIS成熟的功能模塊,依托ArcGIS API進(jìn)行二次開發(fā),系統(tǒng)穩(wěn)定,大大縮短后期的系統(tǒng)功能模塊開發(fā)時(shí)間,提高系統(tǒng)的可擴(kuò)展性和應(yīng)用效果。
本文采用S-57電子海圖數(shù)據(jù),即符合IHO標(biāo)準(zhǔn)《數(shù)字化海道測(cè)量數(shù)據(jù)傳輸標(biāo)準(zhǔn)》的國(guó)際標(biāo)準(zhǔn)電子海圖。國(guó)際標(biāo)準(zhǔn)電子海圖是按S-57標(biāo)準(zhǔn)的要求組織的描寫海域地理信息和航海信息的數(shù)字產(chǎn)品,主要以描述海域要素為主,詳細(xì)表示水深、航行障礙物、助航標(biāo)志、港口設(shè)施、潮流、海流等要素的數(shù)字化信息。電子海圖數(shù)據(jù)文件的命名已經(jīng)嚴(yán)格規(guī)范設(shè)定,按照IHO要求和規(guī)定編制,000是標(biāo)準(zhǔn)電子海圖文件格式的后綴,其封裝結(jié)構(gòu)是一種高壓縮的數(shù)據(jù)交換格式。中國(guó)海事電子海圖的數(shù)據(jù)文件名表現(xiàn)形式為CN******.000,以CN331340.000為例,其中“CN”是中國(guó)海事的代碼(由IHO統(tǒng)一分配)、數(shù)字“3”是航海用途(表示沿海、Coastal),31340表示圖幅編號(hào);小改正更新數(shù)據(jù)文件表現(xiàn)形式是CN******.nnn,其含義與基礎(chǔ)數(shù)據(jù)文件名的意義相同,但后綴根據(jù)小改正更新次數(shù)進(jìn)行編號(hào),最大可達(dá)到999次,如第十次小改正更新,其文件名是CN******.010[3,4]。
電子海圖根據(jù)空間信息的數(shù)據(jù)結(jié)構(gòu)主要包括兩大類:光柵式電子海圖和矢量式電子海圖。其各自特點(diǎn)如表1所示。
電子海圖分類 表1
從上表可以看出,矢量電子海圖數(shù)據(jù)占用空間更小,矢量繪制海圖符號(hào)顯示效果更佳,支持各種空間分析、數(shù)據(jù)更新。移動(dòng)平臺(tái)內(nèi)存空間有限,考慮到需要海上作業(yè)、離線加載海圖數(shù)據(jù)等問(wèn)題,矢量電子海圖的優(yōu)勢(shì)可以得到更好的發(fā)揮。
000海圖文件的解析用C++來(lái)實(shí)現(xiàn),而Android主流應(yīng)用的開發(fā)使用Java語(yǔ)言,因此涉及C++與Android端Java代碼的對(duì)話問(wèn)題,需要實(shí)現(xiàn)兩者之間的無(wú)障礙交流;為了解決這一問(wèn)題,本文選擇采用NDK工具和JNI技術(shù),也是目前Android開發(fā)解決此類相關(guān)問(wèn)題的主流途徑。
(1)NDK介紹
眾所周知,Android相關(guān)應(yīng)用軟件的開發(fā),都是以Java作為主流開發(fā)語(yǔ)言,這主要是因?yàn)锳ndroid SDK使用Java語(yǔ)言編寫。但在實(shí)際程序開發(fā)中,同樣支持C/C++,即所謂的原生編程。Android系統(tǒng)架構(gòu)下的核心庫(kù)是一個(gè)由C/C++編寫的庫(kù)的集合,因此,可以認(rèn)為,Android平臺(tái)實(shí)際是由C/C++搭建,由C/C++編程也成為現(xiàn)實(shí)[8]。
為了在系統(tǒng)底層支持“Java與C/C++”的交換開發(fā),催生了NDK(Native Development Kit)。NDK是一個(gè)工具集,支持開發(fā)者使用本地代碼(C/C++)進(jìn)行程序部分功能的開發(fā)。NDK的出現(xiàn),使得開發(fā)者可以重用一些成熟的C/C++本地庫(kù)來(lái)完成程序某些特定功能的開發(fā),從而提高程序性能。
C/C++的嵌入,豐富了Android的開發(fā);同時(shí),C/C++語(yǔ)言本身的特性,也使NDK給Android開發(fā)帶來(lái)了一系列的天然優(yōu)勢(shì):
①明顯提高代碼的安全性。應(yīng)用層主流語(yǔ)言Java被反編譯難度較低,而以C/C++編寫的動(dòng)態(tài)庫(kù)的反編譯過(guò)程則要困難得多。
②對(duì)本地開源動(dòng)態(tài)庫(kù)的利用更加方便。NDK的出現(xiàn),可以大大提高這些開源庫(kù)的使用,不僅可以有效重用現(xiàn)有代碼,還可以有效提高程序開發(fā)的效率。
③明顯提高代碼的執(zhí)行效率。C/C++語(yǔ)言本省的高性能性,將其進(jìn)行較高性能的應(yīng)用邏輯層面的開發(fā)時(shí),可以大大優(yōu)化代碼的執(zhí)行效率。
④提高代碼的可移植性。本地C/C++動(dòng)態(tài)庫(kù)以 .so庫(kù)的形式獨(dú)立存在,可以方便地應(yīng)用于其他的嵌入式平臺(tái),明顯提高代碼的重用性。
(2)JNI技術(shù)混編
JNI,即Java Native Interface,Java本地接口;用來(lái)實(shí)現(xiàn)Java代碼和本地C/C++代碼的交互。
NDK作為谷歌開發(fā)推出的開發(fā)和編譯工具集,主要用于Android的JNI開發(fā),NDK提供Java和C/C++交互的環(huán)境,用來(lái)實(shí)現(xiàn)Java代碼與本地的C/C++的相互調(diào)用。比如,當(dāng)我們需要使用某個(gè)函數(shù),基于效率等原因,函數(shù)用C/C++語(yǔ)言在NDK環(huán)境中一個(gè)類文件中實(shí)現(xiàn),然后將該類文件打包成so動(dòng)態(tài)庫(kù);利用JNI技術(shù),我們只需在Java層加載上述本地動(dòng)態(tài)庫(kù)、定義一個(gè)JNI式的接口,便可以實(shí)現(xiàn)語(yǔ)言之間的交互,如圖1所示。
圖1 JNI應(yīng)用流程圖
通過(guò)Android中的應(yīng)用程序框架,可以簡(jiǎn)單、直接地看出JNI給程序調(diào)用帶來(lái)的變化。正常情況下的Android框架:最上層是Android的應(yīng)用程序代碼,為Java語(yǔ)言,中間層是Framework框架層,為C/C++代碼,通過(guò)Framework層進(jìn)行系統(tǒng)的調(diào)用,調(diào)用系統(tǒng)的底層庫(kù)函數(shù)和Linux內(nèi)核,如圖2所示。
圖2 Android框架圖
圖3 使用JNI的Android框架圖
使用JNI時(shí)的Android框架:不再經(jīng)過(guò)Framework框架層,通過(guò)JNI直接調(diào)用本地開發(fā)者編寫的C/C++代碼,本地代碼最后通過(guò)NDK環(huán)境編譯成so動(dòng)態(tài)庫(kù),該動(dòng)態(tài)庫(kù)通過(guò)JNI提供的一個(gè)Stable的ABI(二進(jìn)制程序接口application binary interface)調(diào)用Linux內(nèi)核,如圖3所示。
上述兩張圖2和3,可以看出JNI是連接Android框架層(Framework-C/C++)和應(yīng)用框架層(Application Framework-Java)的紐帶。
本文研究選擇ArcGIS Runtime SDK for Android作為系統(tǒng)開發(fā)框架,雖然ArcGIS的API技術(shù)已相對(duì)成熟,但ArcGIS SDK并不能解析和繪制S-57電子海圖矢量格式的000文件。通過(guò)對(duì)NDK的研究和JNI技術(shù)的了解,本文選擇用標(biāo)準(zhǔn)C++解析000文件讀進(jìn)內(nèi)存,利用JNI技術(shù),然后用Java進(jìn)行繪制的模式進(jìn)行矢量海圖的繪制顯示,簡(jiǎn)單的基本流程如下圖4所示。這么做的好處就是文件的解析部分是可以跨平臺(tái)運(yùn)行的,以后如果要在其他平臺(tái)上布設(shè)移動(dòng)海圖系統(tǒng)就可以直接使用這里的解析模塊而不用重新解析從頭開始。繪制的部分由于要考慮到不同操作平臺(tái)的繪制環(huán)境,故沒有必要做成跨平臺(tái)的通用模塊,這樣還可以利用不同平臺(tái)對(duì)自有繪制引擎的加速功能,從而使繪制更加高效。
圖4矢量海圖繪制流程
(3)ArcGIS Runtime SDK for Android介紹
ArcGIS Runtime SDK for Android為Android平臺(tái)上開發(fā)地理信息系統(tǒng)產(chǎn)品提供了最基本的地理信息系統(tǒng)相關(guān)功能的開發(fā)框架,本文選擇ArcGIS Runtime SDK for Android作為系統(tǒng)開發(fā)的技術(shù)框架,可以充分利用其API在地圖應(yīng)用層面目前已具備的成熟的技術(shù)支持。其主要功能包括:數(shù)據(jù)加載、地圖查詢、數(shù)據(jù)展示、外業(yè)數(shù)據(jù)采集、數(shù)據(jù)編輯、數(shù)據(jù)同步。
基于ArcGIS Runtime SDK for Android進(jìn)行二次開發(fā),能夠大大改善之前海圖系統(tǒng)零起步自主研發(fā)導(dǎo)致的系統(tǒng)不穩(wěn)定性,而且對(duì)于后期的系統(tǒng)可拓展性可以提供很好的支持。
ArcGIS for AndroidSDK提供各種類型的圖層類,各圖層類繼承關(guān)系如圖5所示。其中,DynamicLayer提供自定義矢量繪制接口,對(duì)于000矢量電子海圖的繪制,通過(guò)繼承DynamicLayer自定義圖層來(lái)實(shí)現(xiàn),做到對(duì)ArcGIS for Android框架的無(wú)縫對(duì)接。
圖5 圖層類繼承關(guān)系圖
為了實(shí)現(xiàn)矢量電子海圖解析的跨平臺(tái)性,提高整個(gè)海圖系統(tǒng)在平臺(tái)間的可移植性,提高代碼的使用率,000矢量海圖的解析部分采用標(biāo)準(zhǔn)C++來(lái)完成,NDK環(huán)境和JNI技術(shù)的引入,使得Android開發(fā)環(huán)境對(duì)于標(biāo)準(zhǔn)C++具有比較良好的兼容性,不僅支持調(diào)用C++封裝的底層庫(kù),而且支持Java和C++混編,最終將解析的部分打包成so動(dòng)態(tài)庫(kù)供上層繪制模塊調(diào)用。解析模塊整體上分為兩個(gè)部分,對(duì)000海圖文件和符號(hào)庫(kù)進(jìn)行分離解析。
不同平臺(tái)具有各自不同的繪制引擎,同時(shí)不同的操作平臺(tái)對(duì)于自身繪制引擎的支持性也相對(duì)較好,并且調(diào)用起來(lái)也更加方便;本文000矢量海圖的具體繪制,采用Android自帶的繪制引擎Skia進(jìn)行。Skia Graphics Library(SGL)是一個(gè)由C++編寫的開放源代碼圖形庫(kù),最初由Skia公司開發(fā),后由Google收購(gòu),搭配OpenGL ES,成為Android的專屬繪制引擎庫(kù)[5]。Skia主要有以下幾個(gè)特點(diǎn)[9]:
①高度優(yōu)化的軟件rasteriser(module sgl/);
②選擇性透過(guò)OpenGL ES,加速特定操作,如shader與textures(module gl/);
③較強(qiáng)的動(dòng)畫處理能力(module animator/);
④內(nèi)建SVG支援(module svg/);
⑤內(nèi)建若干image codec,如PNG,JPEG,GIF,BMP(modules images/);
⑥具有一定的文字處理功能,但對(duì)于不太常見的文字的處理相對(duì)不足;
Android對(duì)Skia的調(diào)用是一個(gè)比較經(jīng)典JNI式的調(diào)用過(guò)程,這與下面矢量繪制的調(diào)用過(guò)程有異曲同工之處;JNI放在框架的JNI目錄下面的Graphic目錄;Skia以第三方組件的身份,放在external目錄下面。Android對(duì)Skia的調(diào)用流程如圖6所示。
圖6 Android調(diào)用Skia流程圖
海圖適量繪制的過(guò)程總體思想就是解析、繪制、顯示三過(guò)程上下層環(huán)境的分離、開發(fā)語(yǔ)言Java/C++的交互;最后形成獨(dú)立的視圖控件。實(shí)現(xiàn)解析過(guò)程的可移植性、跨平臺(tái)性;利用JNI實(shí)現(xiàn)上下層環(huán)境Java/C++語(yǔ)言的交互、海圖的繪制;通過(guò)自定義開發(fā)ArcGIS for Android View圖層類,實(shí)現(xiàn)海圖顯示圖層的模塊化、獨(dú)立性。整個(gè)調(diào)用繪制過(guò)程如圖7所示。
圖7 海圖矢量繪制圖
海圖矢量繪制具體步驟如下:
(1)首先是海圖000文件和符號(hào)庫(kù)文件的解析。該過(guò)程發(fā)生在C++底層,這是一個(gè)可移植的過(guò)程,桌面版、IOS平臺(tái)均可適用;
(2)將解析結(jié)果內(nèi)存塊轉(zhuǎn)化為bitmap。解析結(jié)果內(nèi)存對(duì)象ENCProject到海圖bitmap圖像的過(guò)程發(fā)生在Android NDK環(huán)境下的C++底層,利用Android的Skia圖形庫(kù)方法DrawMap方法將內(nèi)存塊ENCProject繪制出bitmap;
(3)利用JNI將C++底層bitmap上傳到Android應(yīng)用層java類。該過(guò)程符合Android對(duì)Skia JNI式的調(diào)用過(guò)程,將結(jié)果返回到上層Java層。
(4)自定義新的View圖層類TeleSeaMapServiceLayer。通過(guò)覆寫繼承自DynamicLayer的TeleSeaMapServiceLayer的getImage方法,接收底層傳出的bitmap。
(5)采用ArcGISAPI類MapView加載地圖場(chǎng)景方法addLayer,實(shí)現(xiàn)S-57海圖圖層的顯示。
(1)開發(fā)環(huán)境
海圖系統(tǒng)采用AndroidStudio作為開發(fā)平臺(tái),開發(fā)語(yǔ)言使用Java和標(biāo)準(zhǔn)C++,采用ArcGIS for Android作為開發(fā)接口,數(shù)據(jù)庫(kù)使用Sqlite。
測(cè)試環(huán)境
主要測(cè)試設(shè)備包括Galaxy Note Ⅱ和Galaxy Tab Pro T320。各項(xiàng)參數(shù)指標(biāo)如表2所示。
測(cè)試參數(shù) 表2
(2)效果展示
S-52標(biāo)準(zhǔn)對(duì)海圖的顯示做了基準(zhǔn)規(guī)范,將航道圖顯示分類為以下三種:
①基礎(chǔ)顯示:指不能從顯示中刪除的,由那些在任何情況下都需要的信息所組成的SENC信息層?;A(chǔ)顯示作為標(biāo)準(zhǔn)顯示的一部分,并不能滿足安全航行的需要。
②標(biāo)準(zhǔn)顯示:指當(dāng)航道圖默認(rèn)情況下在電子海圖顯示與信息系統(tǒng)上顯示時(shí)所展示出的系統(tǒng)電子航海圖(SENC)信息。在實(shí)際航海應(yīng)用時(shí),相關(guān)工作人員可根據(jù)需要選擇性顯示系統(tǒng)航道圖的信息,同時(shí)可以進(jìn)行相關(guān)修改。
③所有其他信息:指不包含在標(biāo)準(zhǔn)顯示中的航道圖信息、它僅在需要時(shí)才顯示[10]。
實(shí)驗(yàn)結(jié)果表明,矢量電子海圖的顯示達(dá)到預(yù)定目標(biāo),尤其是對(duì)精細(xì)化海圖符號(hào)的顯示非常成功,如圖8所示。
圖8矢量海圖顯示效果圖
相比傳統(tǒng)tpk瓦片柵格海圖,矢量電子海圖所占存儲(chǔ)空間更小,大大提高了移動(dòng)端海圖顯示的應(yīng)用范圍。矢量電子海圖的顯示質(zhì)量更好,海圖縮放不失真;同時(shí),從圖8可以看出,矢量電子海圖實(shí)現(xiàn)了對(duì)海圖符號(hào)顯示精度和顯示質(zhì)量的雙重保障,解決了瓦片柵格海圖符號(hào)標(biāo)識(shí)模糊、位置不明確的問(wèn)題;并且,本文實(shí)現(xiàn)可以隨意切換實(shí)時(shí)渲染顯示不同專題的海圖符號(hào),相比柵格海圖“一個(gè)專題符號(hào)海圖就需要重新打包一份對(duì)應(yīng)的GB級(jí)別的柵格瓦片”,這完全是跨越式的進(jìn)步。
海洋地理空間的發(fā)展是這個(gè)時(shí)代的主旋律。電子海圖作為海上作業(yè)的必備工具,智能移動(dòng)設(shè)備的發(fā)展推動(dòng),對(duì)矢量電子海圖的需求越來(lái)越大。本文提出通過(guò)繼承ArcGIS DynamicLayer,自定義海圖圖層TeleSeaMapServiceLayer,實(shí)現(xiàn)了ArcGIS for Android下的矢量電子海圖的可視化,可視化效果顯著。同時(shí),基于ArcGIS for Android的二次開發(fā),有助于后期可視化系統(tǒng)的維護(hù)和可拓展性。對(duì)于系統(tǒng)的優(yōu)化和相關(guān)功能的開發(fā),有待于后期進(jìn)一步開發(fā)。
[1] 齊勝利. 基于Android的移動(dòng)電子海圖平臺(tái)研究[D]. 大連:大連海事大學(xué),2012.
[2] 李超,潘明陽(yáng),李邵喜等. 基于Android的電子海圖顯示系統(tǒng)研究與實(shí)現(xiàn)[J]. 大連海事大學(xué)學(xué)報(bào),2013,39(4):55~58.
[3] 陳輝. Web方式下電子海圖的顯示技術(shù)研究與應(yīng)用[D]. 武漢:武漢理工大學(xué),2011.
[4] 董才華,秦臻. 電子海圖數(shù)據(jù)讀取與顯示技術(shù)[J]. 中國(guó)航海,2012,35(4):22~25.
[5] 徐鐵.電子海圖數(shù)據(jù)庫(kù)及其索引技術(shù)研究[D]. 上海海運(yùn)學(xué)院,2003.
[6] 徐永峰.基于分層動(dòng)態(tài)網(wǎng)格的電子海圖顯示技術(shù)研究[D]. 上海:上海海事大學(xué),2006.
[7] 董曉光,李樹軍,李改肖等. 移動(dòng)平臺(tái)下電子海圖矢量數(shù)據(jù)訪問(wèn)優(yōu)化方法[J]. 海洋測(cè)繪,2015,35(4):57~59.
[8] 王有祿,李代平. Android系統(tǒng)下基于NDK方式的圖形開發(fā)[J]. 計(jì)算機(jī)系統(tǒng)應(yīng)用,2013(12):56~59.
[9] 邵哲平,孫騰達(dá),潘家財(cái)?shù)? 基于ECDIS和AIS的船舶綜合信息服務(wù)系統(tǒng)的開發(fā)[J]. 中國(guó)航海,2007,2:7.