鄭祿喜 羅立宏
關(guān)鍵詞:三維地圖;定位;實時導(dǎo)航;Web平臺;Cesium
0 引言
隨著經(jīng)濟的不斷發(fā)展,高樓大廈拔地而起,道路橋梁不斷增加,因此城市的面貌日新月異?,F(xiàn)在人們來到一座陌生的城市,不再像以前那樣記住顯眼的標(biāo)志,摸索著走幾段路就能到達目的地。通常都有著目的地就在附近的想法,但怎么都到達不了目的地,詢問當(dāng)?shù)鼐用癫诺弥_的路線。因現(xiàn)今的道路越發(fā)復(fù)雜,所以電子地圖成為出行必備的應(yīng)用。但對于一些方向感較弱的人來說,當(dāng)前的電子地圖應(yīng)用給予的地理位置信息還不是很直觀,他們?nèi)匀粫l(fā)生到達不了目的地的可能性。
三維可視化技術(shù)能夠給人們帶來強烈的視覺感受,即相比于平面地圖和哥倫布地圖,三維地圖能夠提供更為直觀的地理位置信息。國內(nèi)外對于三維地圖領(lǐng)域相關(guān)的研究力度很大,黃娟娟等[1]在Unity3D上實現(xiàn)景區(qū)的可視化,然后利用改進隱性馬爾科夫模型的地圖匹配算法解決了三維地圖定位精度低的問題;田風(fēng)勛[2]基于現(xiàn)有的PF等數(shù)字?jǐn)z影測量系統(tǒng)生產(chǎn)平臺,利用3DMax等建模工具,通過C#語言輔以SkyLine開發(fā)包開發(fā)實景三維地圖;王亞美[3]、孫偉[4]各自的團隊都利用OpenGL ES在Android平臺上實現(xiàn)了三維地圖的可視化系統(tǒng);???等[5]提出使用Kinect等深度相機生成三維地圖以及利用相機拍攝的2D圖像在三維地圖中進行位姿跟蹤,解決了室內(nèi)無法接收GPS信號定位當(dāng)前位置生成三維地圖的問題;Hildebrandt等[6]提出了面向服務(wù)的、交互式的大規(guī)模3D城市模型三維可視化系統(tǒng)架構(gòu),該架構(gòu)為大規(guī)模3D城市模型的安全、穩(wěn)健分布和交互式呈現(xiàn)提供了一種解決方案。
上述研究都通過不同的方法完成了三維地圖的構(gòu)建,但都需要安裝相應(yīng)的插件或軟件進行開發(fā),難以實現(xiàn)跨平臺使用,并且研發(fā)產(chǎn)品可能在不同的平臺會不兼容。若基于Web平臺開發(fā)三維地圖,就能實現(xiàn)跨平臺的效果。由于以前各種條件的限制,在Web上渲染的3D圖形和三維交互的效果都不如在PC和嵌入式設(shè)備上的效果,所以很少基于Web平臺開發(fā)三維應(yīng)用。但3D繪圖標(biāo)準(zhǔn)WebGL的出現(xiàn),加上瀏覽器的性能越來越強,如今網(wǎng)頁上也能夠繪制和渲染復(fù)雜、精美的3D圖形。WebGL技術(shù)標(biāo)準(zhǔn)不需要安裝插件,只用一個文本編輯器和支持WebGL的瀏覽器就可以開發(fā)具有復(fù)雜3D圖形的網(wǎng)站或3D網(wǎng)頁游戲。因此,多種基于JavaScript 封裝WebGL API 的3D 引擎逐漸出現(xiàn),如Babylon.js、Three.js和Cesium.js等,而Cesium.js很適合作為在三維地形、仿真和GIS等領(lǐng)域進行可視化的圖形庫,如袁凌等[7]將地形數(shù)據(jù)切片,利用Cesium加載地形、谷歌影像和風(fēng)力發(fā)電機模型等要素構(gòu)建三維場景,實現(xiàn)了風(fēng)電場地形的三維可視化,能夠輔助風(fēng)電場的建設(shè)和風(fēng)機運行狀態(tài)監(jiān)測;蘇昊翔等[8]在Cesium平臺上開發(fā)了衛(wèi)星載荷可視化的仿真系統(tǒng),該系統(tǒng)解決了跨平臺使用,無須使用特定軟件進行展示的問題,有利于仿真結(jié)果的可視化共享;GRAEME F.CLARK等[9]使用CesiumJS結(jié)合大數(shù)據(jù)開發(fā)一款基于Web的澳大利亞海洋碎片數(shù)據(jù)庫可視化工具,給專業(yè)和民間科學(xué)家提供多種方式探索海洋數(shù)據(jù);Kilsedar,CE 等[10]利用CityGML和CesiumJS進行三維地理空間數(shù)據(jù)可視化并模擬洪水發(fā)生的過程,達到幫助有關(guān)適應(yīng)措施和減輕洪水影響的知情決策過程的目的;畢碩本等[11]在模擬洪水災(zāi)害過程的基礎(chǔ)上,還將熱帶氣旋路徑、所致?lián)p失等其他災(zāi)害信息整合于Cesium的三維地球中。因此,本文通過Cesium.js結(jié)合高德地圖的Web服務(wù)API實現(xiàn)Web平臺的三維地圖實時導(dǎo)航服務(wù)。
1 Cesium 簡介
Cesium是用于創(chuàng)建強大的3D地理空間應(yīng)用程序的基礎(chǔ)開放平臺,也是一款開源的基于JavaScript的3D 地圖框架。Cesium 開發(fā)平臺上有著Cesium Ion、ICoens是ium一JS個、C提e供siu3mDfoTrileUsn和rea地l三理空個間主數(shù)要據(jù)平的臺平。臺C,e它siu有m3D Tiles流式傳輸?shù)淖羁斓墓艿溃梢园?D數(shù)據(jù)上傳到Cesium Ion中,在使用CesiumJS開發(fā)時可以通過申請的access token 直接訪問Cesium Ion 中的數(shù)據(jù)源;CesiumJS是一個開放源代碼JavaScript 庫,用于創(chuàng)建具有最佳性能、精度、視覺質(zhì)量和易用性的3D地球和地圖;Cesium for Unreal是游戲引擎中的第一個高精度地球儀,將Cesium的真實世界的細(xì)節(jié)和準(zhǔn)確性帶入了模擬環(huán)境。
CesiumJS是一個三維可視化引擎,底層核心基于WebGL技術(shù)構(gòu)建,以WebGL技術(shù)作為其圖形渲染引擎,所以可以在支持WebGL的瀏覽器上運行,包括手機、平板、電腦的瀏覽器,所以它具有跨平臺的特點[12]。它有可精確分析的高精度WGS84地球儀,并提供了與地理空間坐標(biāo)相關(guān)的計算功能;支持繪制幾何圖形;能夠加載KML、GeoJSON、CZML和terrain等多種類型的空間數(shù)據(jù)文件;支持3D Tiles、glTF模型、時間動態(tài)數(shù)據(jù);可自由切換2D、2.5D、3D視圖模式。
一個完整的Cesium應(yīng)用程序由五層組成,自下而上分別是核心層(Core) 、渲染器層(Renderer) 、場景層(Scene) 、數(shù)據(jù)源層(DataSources) 、部件層(Widgets) 。核心層主要是數(shù)學(xué)運算類,例如笛卡爾坐標(biāo)運算、地理坐標(biāo)運算和四元數(shù)運算等;渲染器層是WebGL的高級抽象和GLSL庫;場景層囊括了地形和影像引擎、三維模型、幾何圖形、矢量數(shù)據(jù)和攝像機等對象;數(shù)據(jù)源層是一個高級Entity API,封裝了場景類型和時間動態(tài)屬性;部件層是場景中的一些小部件,如動畫、視圖模式切換、全屏等控件。
2 關(guān)鍵技術(shù)
2.1 WGS84坐標(biāo)與笛卡爾坐標(biāo)的轉(zhuǎn)換
Cesium項目中經(jīng)常涉及坐標(biāo)轉(zhuǎn)換,如加載模型時的初始位置、模型或?qū)嶓w的空間位置變換等,在執(zhí)行這些操作時,位置信息幾乎都是輸入經(jīng)緯度坐標(biāo),但Cesium最終都會把坐標(biāo)轉(zhuǎn)換為笛卡爾坐標(biāo)來表達空間位置信息。Cesium中有兩種坐標(biāo)系,分別是WGS84 坐標(biāo)系(以下簡稱為84坐標(biāo))和墨卡托投影坐標(biāo)系。本文使用的是84坐標(biāo),但Cesium中沒有84坐標(biāo)相對應(yīng)的類,所以用弧度表示經(jīng)緯度,可以通過式(1)求得經(jīng)緯度的弧度形式,R 表示弧度,D 表示經(jīng)緯度角度。
84坐標(biāo)轉(zhuǎn)換為笛卡爾坐標(biāo)[13]:已知84坐標(biāo)中橢球中 的 長 半 軸 a = 6378137.0、短 半 軸 b = 6356752.3142451793、緯度B、經(jīng)度L、海拔H。根據(jù)式(2)求得笛卡爾坐標(biāo)(X,Y,Z),式(2)中e1為橢球的第一偏心率,N 為橢圓曲率半徑,它們分別可根據(jù)式(3)求得:
笛卡爾坐標(biāo)轉(zhuǎn)換為84坐標(biāo):將式(2)進行反向推導(dǎo),可得到式(4),通過式(5)可將笛卡爾坐標(biāo)轉(zhuǎn)換為84 坐標(biāo),但求得的84坐標(biāo)是弧度形式,可通過式(2)推導(dǎo)出轉(zhuǎn)換為經(jīng)緯度形式的式(5)。
2.2 偏移路線檢測
在導(dǎo)航過程中,判斷當(dāng)前位置是否偏離了規(guī)劃的路線是很重要的,若偏離了路線,則需要重新根據(jù)當(dāng)前位置作為起點重新規(guī)劃路線。本文采用了點是否在多邊形內(nèi)作為判斷當(dāng)前位置是否偏離路線的方法,點在多邊形外則表示偏離了路線。當(dāng)前位置以點表示,構(gòu)成該點是當(dāng)前位置的經(jīng)緯度坐標(biāo),規(guī)劃的路線是以曲線表示,構(gòu)成該曲線是該路線的經(jīng)緯度坐標(biāo)集合。以曲線為中心,計算一個半徑為2 m的緩沖區(qū)作為多邊形,該多邊形是由點集P={(xi,y≤ i) | 1≤i≤n, n≥3}構(gòu)成。當(dāng)2 i≤n-1時,Pi分別與相鄰的兩個點Pi-1、Pi+1相互連接構(gòu)成一條折線,最后P1與Pn連接形成閉合而構(gòu)成一個多邊形。判斷點P0(x0, y0)是否在多邊形內(nèi)的過程如下:
1) 判斷點P0是否在多邊形的邊界框bbox內(nèi)。計算點集P 中x、y 的最值Xmin、Xmax、Ymin、Ymax,從這些最值中可組合成四個點,分別是點A(Xmin,Ymax)、B(Xmax,Y( max)、C Xmax,Ymin)、D(Xmin,Ymin)、這四個點可構(gòu)成一個邊界框bbox (圖1 a),然后判斷點P0 是否在bbox里面,即Xmin≤x0≤ Xmax 且Ymin≤y0≤Ymax。若不在bbox范圍內(nèi),表示點P0在多邊形外,否則跳到步驟2)。
2) 利用射線法判斷點P0與多邊形的關(guān)系。從任意一點繪制一條到達點P0的直線(圖1 b),統(tǒng)計該條直線與多邊形相交的邊數(shù)k,通過式(6)計算出k 的奇偶性,點P0與多邊形的關(guān)系可用式(7)表示[14]。因為有一種點P0剛好就在多邊形的邊上,但k 為偶數(shù)的特殊情況,所以當(dāng)k 為偶數(shù)時,還需要判斷點P0是否落在多邊形的邊上,跳到步驟3)。
3) 利用叉積法判斷點P0與多邊形的邊的關(guān)系。多邊形的邊集是它的點集中相鄰兩點和首尾兩點連接而構(gòu)成的邊,只要點P0在邊集上任一條邊上,則點P0就是在多邊形的邊上。可用叉積判斷點P0與邊P1P2的關(guān)系,邊P1 P2是由點P1(x1, y1)和點P2(x2, y2)連接而成,通過式(8)可求得點P0與邊P1 P2的叉積Pc,若Pc = 0,則點P0與邊P1 P2共線[15]。
2.3 相機模式
2.3.1 相機跟隨
在三維地圖的實時導(dǎo)航中,場景中的相機需要一直跟隨表示當(dāng)前位置的標(biāo)志,所以需要實現(xiàn)相機跟隨的效果。Cesium中有很多函數(shù)可以改變相機的位置,但這些函數(shù)要么只能改變相機的視角,沒有平滑的跟隨效果,要么只有跟隨效果,相機的視角卻是固定的,所以需要將兩者結(jié)合起來,實現(xiàn)相機的視角始終跟隨在目標(biāo)的后面。
Viewer中有一個trackedEntity的屬性,一旦給該屬性賦值,相機將一直跟隨該屬性中的目標(biāo),它的實現(xiàn)原理是通過式(10)計算出相機的新位置T,其中C 表示被跟隨目標(biāo)的當(dāng)前位置,D 表示相機的偏移量。
雖然trackedEntity解決了相機平滑的跟隨,但帶來了相機視角固定在一個方向的問題,即相機視角不會隨著跟隨目標(biāo)的方向變化而變化,所以需要在這的基礎(chǔ)上,使相機的方向隨著跟隨目標(biāo)的方向變化而變化。實現(xiàn)方法如下:一旦跟隨目標(biāo)的位置發(fā)生改變,就通過式(11)、式(12)計算目標(biāo)之前的位置點P(L1, B1) 和當(dāng)前位置點Q(L2, B2)的方位角A(點P、Q 坐標(biāo)中的L、B 分別表示經(jīng)度、緯度),然后利用式(5)把方位角A 轉(zhuǎn)換成角度形式,最后對方位角A 取模360求得最終的方位角A,其中點P、Q的經(jīng)緯度是以弧度來表示[16],一旦方位角A>5,就使相機繞Z軸旋轉(zhuǎn)A 度。
2.3.2 第一人稱視角
相機模式設(shè)為第一人稱視角,相當(dāng)于把相機當(dāng)成人的眼睛,即相機的朝向能夠和人的視線一樣變換,通過監(jiān)聽DeviceOrientationEvent事件獲取設(shè)備的物理旋轉(zhuǎn)信息作為相機朝向改變的數(shù)據(jù)源實現(xiàn)和人的視線一樣變換。它的事件屬性有α、β、γ 三個屬性,分別表示設(shè)備繞Z、X、Y軸旋轉(zhuǎn)的角度,利用α 表示視線左右搖擺,β 表示上下?lián)u擺。實現(xiàn)第一人稱視角的功能只需α、β 兩個屬性,當(dāng)設(shè)備指向正北時α=0,設(shè)備逆時針旋轉(zhuǎn),則α 值增加,α 的范圍為[0,360];當(dāng)設(shè)備水平擺放時β=0,設(shè)備頂部向上方傾斜則β 值增加,β 的范圍為[-180,180]。
通過α 控制相機左右兩側(cè)的朝向和導(dǎo)航標(biāo)志模型的朝向,β 控制相機上下兩方的朝向。基于用戶手持設(shè)備的習(xí)慣,相機上下兩方的朝向需要做一定的限制,即β=0時,相機朝向為地面;β=45時,相機朝向為水平方向;β=90時,相機朝向為天空。假設(shè)相機上下旋轉(zhuǎn)角度A'的最佳配置為:A'=-90表示地面;A'=0表示水平方向;A'=30表示天空,通過式(13)可獲得最終的旋轉(zhuǎn)角度A'。
3 功能實現(xiàn)
3.1 開發(fā)前的準(zhǔn)備
把項目中需要加載的資源上傳到Cesium Ion中(需要在Cesium官網(wǎng)中注冊賬號并申請一個Access Token) ,如3D Tiles、模型和圖片等資源,并獲得資源的accessId;還需要在高德開放平臺注冊為開發(fā)者并創(chuàng)建一個Web服務(wù)應(yīng)用,得到該應(yīng)用的Key。
3.2 搭建Cesium 場景
3.3 路徑規(guī)劃
在頁面中添加關(guān)于路徑規(guī)劃功能的控件,如起點、終點的輸入框、右鍵菜單、規(guī)劃路線的信息顯示框等控件,并根據(jù)情況控制它們的顯示和隱藏,這些前提準(zhǔn)備完成之后,就可以進行路徑規(guī)劃功能的實現(xiàn),該功能的流程圖如圖2所示。
1) 獲取起點和終點的經(jīng)緯度。獲取經(jīng)緯度的方式有兩種,一是在起點、終點輸入框中輸入地址,利用高德的地理編碼服務(wù)將該地址轉(zhuǎn)化為經(jīng)緯度;二是單擊鼠標(biāo)右鍵彈出菜單,點擊菜單中的起點、終點來標(biāo)記起點和終點,通過右鍵點擊的屏幕坐標(biāo)轉(zhuǎn)化為笛卡爾坐標(biāo),再將笛卡爾坐標(biāo)轉(zhuǎn)化為經(jīng)緯度,最后需要將84坐標(biāo)系的經(jīng)緯度轉(zhuǎn)化為高德地圖坐標(biāo)系的經(jīng)緯度,Cesium 中的viewer.camera.pickEllipsoid()函數(shù)可將屏幕坐標(biāo)轉(zhuǎn)化為笛卡爾坐標(biāo)。
2) 路徑規(guī)劃。通過ajax請求高德的路徑規(guī)劃服務(wù)接口,如駕車路徑規(guī)劃請求的url:https://restapi.amap.com/v3/direction/driving?origin=longo,lato&destination=longd,latd&key=keyString。url中的參數(shù)origin、destination分別是起點和終點的經(jīng)緯度(longo, lato) , (longd, latd),keyString是用戶申請的Web服務(wù)應(yīng)用key,這些參數(shù)是必填項。除了駕車路徑的接口外,還有公交路徑規(guī)劃和步行路徑規(guī)劃的接口,它們的url分別是: tegrat①ed?hptatpras:m//eretestrasp;i. amap. com/v3/direction/transit/in?②https://restapi.amap.com/v3/direction/walking?pa?rameters。parameters表示請求中的參數(shù),根據(jù)控件中選擇查詢的方式分別向這些url發(fā)起請求。
3) 封裝信息。把返回的json數(shù)據(jù)中的必要信息封裝到一個對象中,如路線的起點和終點經(jīng)緯度、路線的詳細(xì)信息、路線的經(jīng)緯度數(shù)據(jù)等。路線的經(jīng)緯度數(shù)據(jù)的值在結(jié)果中多個經(jīng)緯度拼接成的字符串,需要對其進行分割用數(shù)組儲存,而且結(jié)果中的經(jīng)緯度用于84坐標(biāo)會有一定的偏差,需要對其轉(zhuǎn)化為84坐標(biāo)下的經(jīng)緯度。
4) 繪制路線。把路線的經(jīng)緯度數(shù)據(jù)作為數(shù)據(jù)源,利用GroundPrimitive類來繪制緊貼地形的線段,即路線,并且通過路線的數(shù)據(jù)創(chuàng)建一個SampledPosition? tPrraocpkeErtnyti的ty使實相例機賦沿值著到該一條個路實線體進上行,漫即游可。通過viewer.
路徑規(guī)劃功能的效果如圖3所示。
3.4 實時導(dǎo)航
在實時導(dǎo)航的過程中,需要獲得用戶的當(dāng)前的經(jīng)緯度位置,并需要持續(xù)返回用戶移動時更新的經(jīng)緯度位置,根據(jù)獲得的經(jīng)緯度位置來更新導(dǎo)航標(biāo)志模型的位置和檢測當(dāng)前是否偏離了規(guī)劃的路線。若偏離了路線,則需要根據(jù)當(dāng)前位置重新規(guī)劃路線。一旦自行結(jié)束導(dǎo)航或抵達目的地則導(dǎo)航結(jié)束。該功能的流程圖如圖4所示。
1)Positin獲事取件當(dāng)能前夠位持置續(xù)。獲H得5地用理戶定移位動功時能的中位的置w,這atc一h?特性恰好符合持續(xù)獲得用戶位置的需求,所以需要監(jiān)聽該事件獲得導(dǎo)航過程中用戶的當(dāng)前位置,而該事件的位置信息是以經(jīng)緯度坐標(biāo)形式返回,所以可通過式(1)、式(2)把經(jīng)緯度坐標(biāo)轉(zhuǎn)換為笛卡爾坐標(biāo),然后把該笛卡爾坐標(biāo)設(shè)為導(dǎo)航標(biāo)志模型的新位置。
2) 檢測是否偏離路線。在繪制路徑的同時,也會繪制一個路徑的緩沖區(qū)。該緩沖區(qū)是以路徑為中心繪制半徑2m的多邊形,如圖5中的線段表示路徑,橢圓部分表示路徑的緩沖區(qū)。在獲得新位置坐標(biāo)后,需要檢測新坐標(biāo)是否在該緩沖區(qū)的bbox范圍內(nèi),若在bbox區(qū)域外,則表示當(dāng)前已經(jīng)偏離了路線;若在bbox 區(qū)域內(nèi),則需要通過射線法檢測該坐標(biāo)是否在緩沖區(qū)內(nèi),若在緩沖區(qū)外,則表示當(dāng)前已經(jīng)偏離了路線。
3) 偏離路線。若當(dāng)前位置偏離了路線,則需要以當(dāng)前位置為起點重新規(guī)劃路線。在重新規(guī)劃路徑前需要清空之前路徑的相關(guān)信息,包括路徑途徑點、導(dǎo)航信息和路徑緩沖區(qū)等信息。
4 結(jié)束語
本文通過結(jié)合Cesium與高德Web服務(wù)API實現(xiàn)了Web平臺的三維地圖實時導(dǎo)航服務(wù)、路徑規(guī)劃、路徑漫游等基礎(chǔ)功能,研究了經(jīng)緯度坐標(biāo)與笛卡爾坐標(biāo)轉(zhuǎn)換、點線面的關(guān)系、相機模式等關(guān)鍵技術(shù),達到了在不同的操作系統(tǒng)下都可以通過瀏覽器訪問三維地圖的效果,完成了跨平臺需求。本次研究中的城市模型是白模,這方面有極大的優(yōu)化空間,接下來將嘗試使用傾斜攝影技術(shù)構(gòu)建一個更為真實的城市模型。三維地圖實時導(dǎo)航在交通出行、城市規(guī)劃、景區(qū)、高校、商業(yè)圈等區(qū)域的導(dǎo)航和宣傳等領(lǐng)域都有一定的應(yīng)用價值。