這篇文章是我前段時(shí)間在組內(nèi)進(jìn)行技術(shù)分享的一個(gè)整理撑蚌,通過(guò)這篇文章可以幫你了解我們常見(jiàn)的地圖技術(shù)上遥。
文章內(nèi)容主要包括三個(gè)部分,一是我們常見(jiàn)的地圖(百度地圖争涌、高德地圖等)是如何從基本的底層地圖數(shù)據(jù)展示到前端(瀏覽器粉楚、手機(jī)等)的。二是介紹了一整套的開(kāi)源地圖解決框架亮垫,并且通過(guò)框架模擬了一張魔獸世界地圖jpg文件從切片到發(fā)布再到解析到瀏覽器上的一整套流程模软。第三部分則是回顧了今目標(biāo)android端在解決海外地圖相關(guān)業(yè)務(wù)中的一些嘗試。
一饮潦、地圖的顯示
- 衛(wèi)星燃异,航拍生成原始地圖
- 地圖顯示的第一步就是獲取地圖數(shù)據(jù)了,我們一般通過(guò)衛(wèi)星和航拍獲得原始的地圖數(shù)據(jù)继蜡,如圖回俐,我們得到了一整張的世界地圖。
- 原始地圖切片(經(jīng)緯度稀并,投影)
- 把一張世界地圖顯示到手機(jī)里是不可能的鲫剿,所以就引入了金字塔模型的概念(也就是比例尺),我們可以根據(jù)不同的縮放比例稻轨,顯示不同的分辨率灵莲。在地圖應(yīng)用中,我們用手指縮放和放大地圖殴俱,地圖顯示大小的變換政冻,都是基于金字塔模型來(lái)組織瓦片圖的。我們一般按照制定的經(jīng)緯度和投影的規(guī)則對(duì)地圖進(jìn)行切片线欲,切片和對(duì)應(yīng)級(jí)別的組織形式是一整張切成4份明场,這就是一個(gè)級(jí)別,然后每一小份在切4份李丰,依次類(lèi)推苦锨。通過(guò)下圖可以看到,在這種通用的切片規(guī)則下,非洲西海岸就是經(jīng)緯度的(0舟舒,0)點(diǎn)拉庶。
- 地圖切片發(fā)布成地圖服務(wù)
好了,現(xiàn)在我們瓦片數(shù)據(jù)也有了秃励,現(xiàn)在就該把數(shù)據(jù)發(fā)布成服務(wù)了氏仗,發(fā)布地圖數(shù)據(jù)的web應(yīng)用有很多,國(guó)內(nèi)外各大地圖服務(wù)提供商都有自己的發(fā)布服務(wù)的應(yīng)用夺鲜,開(kāi)源世界也有非常好用的免費(fèi)應(yīng)用Geoserver皆尔,通過(guò)這些應(yīng)用發(fā)布后,生成的地圖服務(wù)就會(huì)如下面鏈接所示币励。
- 前端框架解析地圖服務(wù)展示地圖(瀏覽器慷蠕,手機(jī)view)
- 大家可以看到,上面的地圖服務(wù)打開(kāi)后是以xml的形式提供的食呻,所以砌们,我們需要前端的框架來(lái)解析這種服務(wù),展示地圖搁进。前端框架有很多浪感,國(guó)內(nèi)百度和高德都提供這種框架,開(kāi)源世界也有OpenLayers這種免費(fèi)好用的前端框架饼问。我們打開(kāi)百度地圖的首頁(yè)影兽,通過(guò)瀏覽器看到的地圖,就是通過(guò)百度的js框架解析地圖服務(wù)所展示的莱革。移動(dòng)端的地圖sdk也是一樣的道理峻堰。
-
一整套的開(kāi)源地圖解決方案
1.地圖服務(wù)發(fā)布:GeoServer
GeoServer是一款基于JAVA的地圖發(fā)布web應(yīng)用。
Geoserver官網(wǎng)
2.地理解析數(shù)據(jù)庫(kù)框架:gisgraphy
gisgraphy是一款基于基于JAVA的地理解析/逆地理解析web應(yīng)用盅视,它的內(nèi)置數(shù)據(jù)庫(kù)是PostgreSQL+PostGIS擴(kuò)展捐名,有了它,你就可以制作基于空間的數(shù)據(jù)并進(jìn)行存儲(chǔ)闹击,同時(shí)通過(guò)該框架生成地理解析/逆地理解析服務(wù)供其他人使用镶蹋。
gisgraphy官網(wǎng)
3.前端框架:OpenLayers
OpenLayers 是一個(gè)專(zhuān)為Web GIS 客戶端開(kāi)發(fā)提供的JavaScript 類(lèi)庫(kù)包,用于實(shí)現(xiàn)標(biāo)準(zhǔn)格式發(fā)布的地圖數(shù)據(jù)訪問(wèn)赏半,有了它贺归,你就可以解析各大服務(wù)商的地圖服務(wù)或者是你自己的,并展示到瀏覽器断箫。
OpenLayers官網(wǎng)
二拂酣、制作魔獸地圖
- 準(zhǔn)備一張魔獸地圖jpg的圖片
- 魔獸地圖jpg文件切成瓦片
- 通過(guò)地圖切片工具對(duì)魔獸地圖進(jìn)行切片,我這里切了5-10級(jí)別仲义。
- 發(fā)布魔獸地圖服務(wù)
- 我這里用開(kāi)源框架GeoServer發(fā)布婶熬。
- 百度api解析瓦片并展示到瀏覽器
- 我這里用了百度的js框架解析魔獸地圖服務(wù)剑勾。重點(diǎn)是下圖這段代碼,我這里加載的是本地瓦片赵颅,把它換成地圖服務(wù)的鏈接也是一樣的虽另。
最終效果
三性含、Jingoal海外地圖,定位鸳惯,逆地理解析的實(shí)現(xiàn)
Jingoal安卓端主要用到涉及地圖的框架有高德地圖SDK商蕴,高德定位SDK,和OpenStreetMap的逆地理解析服務(wù)芝发。
1.地圖實(shí)現(xiàn)
地圖顯示遇到的困難
- 高德地圖sdk只提供的國(guó)內(nèi)的地圖數(shù)據(jù)绪商,沒(méi)有國(guó)外數(shù)據(jù)。
解決方案
- 最開(kāi)始設(shè)想是維護(hù)兩套地圖sdk辅鲸,國(guó)內(nèi)用高德地圖格郁,國(guó)外用谷歌地圖。但是最大的問(wèn)題是要想用谷歌地圖必須要手機(jī)安裝谷歌service独悴,很遺憾例书,國(guó)內(nèi)的android手機(jī)是沒(méi)有的,并且安裝需要翻墻刻炒。
- 解析海外地圖的服務(wù)地址决采,通過(guò)高德SDK的TileOverLay類(lèi)中的方法疊加海外地圖圖層 ,需要支出的是坟奥,找到的地圖服務(wù)的規(guī)則必須是球面墨卡托投影的树瞭,否則和高德地圖疊加的話位置會(huì)有偏移,最終找到了OpenStreetMap和GoogleMap的地圖服務(wù)地址爱谁。
OpenStreetMap:
OpenStreetMap地圖服務(wù)瓦片地址
GoogleMap:
GoogleMap地圖服務(wù)瓦片地址
在高德sdk下調(diào)用其他地圖服務(wù)的關(guān)鍵方法如下圖晒喷,怎么樣,是不是和疊加魔獸地圖差不多访敌?其實(shí)原理都是一樣的凉敲,Constants.Google_URL就是地圖服務(wù)的地址。
2.定位
定位遇到的困難
當(dāng)時(shí)版本的定位sdk不支持海外定位寺旺,返回的坐標(biāo)是“火星”坐標(biāo)荡陷。
小tips:地球坐標(biāo)系是GPS返回的WGS-84坐標(biāo)系下的經(jīng)緯度,“火星”坐標(biāo)系是我國(guó)出于保密出發(fā)迅涮,講WGS-84坐標(biāo)系做了非線性加密處理废赞。
定位遇到的問(wèn)題
解決方案
地球<-->火星 坐標(biāo)轉(zhuǎn)換工具類(lèi)
https://github.com/wandergis/coordtransform
3.逆地理解析
逆地理解析遇到的困難
- 如何判斷所在的位置是在國(guó)內(nèi)還是國(guó)外
- 尋找靠譜的海外逆地理解析服務(wù)接口
解決方案
- 關(guān)于判斷坐標(biāo)點(diǎn)是否在國(guó)內(nèi),github上有相關(guān)類(lèi)庫(kù)叮姑,通過(guò)下圖方法判斷唉地,但是可以看到据悔,邊界區(qū)域會(huì)非常不準(zhǔn)。
- 海外位置的逆地理解析极颓,基本上是找國(guó)外提供的逆地理解析服務(wù)來(lái)實(shí)現(xiàn)的,如下是找到的比較穩(wěn)定可靠的解決方案
- 微信的解決方案Foursquar
Foursquar - GoogleMap的googleplace
GooglePlace - OpenStreeMap的逆地理解析服務(wù)
OpenStreeMap
最終選擇了OpenStreeMap的逆地理解析服務(wù)群嗤,因?yàn)榉祷氐臄?shù)據(jù)量小并且比較精確菠隆。
截止到目前的解決方案
上面的一些問(wèn)題,其實(shí)通過(guò)高德不斷的更新sdk已經(jīng)很大程度上解決了狂秘,比如海外地圖數(shù)據(jù)骇径,3.2.1版本的高德sdk已經(jīng)默認(rèn)會(huì)在國(guó)外疊加谷歌地圖的服務(wù)了。高德定位在2.0以后已經(jīng)支持全球定位了者春,也就不用我們自己手動(dòng)的進(jìn)行火星和地球坐標(biāo)的轉(zhuǎn)換了破衔。而判斷是否在國(guó)外,高德定位2.1.0也已經(jīng)提供的api钱烟,準(zhǔn)確度也還可以晰筛。
基于以上,今目標(biāo)android端國(guó)外地圖相關(guān)業(yè)務(wù)基本完成拴袭。
下圖是公司同事在美國(guó)出差幫忙測(cè)試的考勤應(yīng)用读第,地圖展示、定位和逆地理解析都比較準(zhǔn)確拥刻。