手繪圖導(dǎo)航

簡介

通常在項目中需要用到地圖的時候我們會選擇百度、高德等地圖;但有的時候客戶會要求提供基于手繪圖的定位、導(dǎo)游導(dǎo)覽功能,百度-瓦片圖層高德-圖片覆蓋物提供了相應(yīng)的解決方案,我們可以把手繪圖作為瓦片、覆蓋物放在地圖上,但是這種方案有其局限性:必須依托百度、高德地圖本身才能查看手繪圖。

接下來我將為大家?guī)砹硗庖环N解決方案,純手繪圖導(dǎo)游導(dǎo)覽、定位,先看效果圖:

手繪圖導(dǎo)游導(dǎo)覽

NAMapKit

NAMapKit是一個開源的手繪圖框架,支持縮放、地圖標記、高清地圖切片瀏覽、本地手繪圖、在線手繪圖功能。

NAMapKit Demo

Popup Menu

默認情況下NAMapKit的標記點彈出框不夠nice,所以我在github上fork了NAMapKit,并實現(xiàn)了與City Guides by National Geographic這款A(yù)pp中類似的功能:

Fork NAMapKit on github

標記點

普通點標記

普通點的標記可以直接用尺子在手繪圖上量一下,拿到目標點的CGPoint(x,y),之后把這個point作為NAPinAnnotation添加到地圖上,這樣就實現(xiàn)了打點的功能。

當前位置打點

要實現(xiàn)當前位置打點,就得將經(jīng)緯度坐標轉(zhuǎn)換成圖片的平面坐標,以百度地圖來說,它提供了以下轉(zhuǎn)換函數(shù):

// BMKGeometry.h
/**
 *將經(jīng)緯度坐標轉(zhuǎn)換為投影后的直角地理坐標
 *@param coordinate 待轉(zhuǎn)換的經(jīng)緯度坐標
 *@return 轉(zhuǎn)換后的直角地理坐標
 */
UIKIT_EXTERN BMKMapPoint BMKMapPointForCoordinate(CLLocationCoordinate2D coordinate);

/**
 *將投影后的直角地理坐標轉(zhuǎn)換為經(jīng)緯度坐標
 *@param mapPoint 投影后的直角地理坐標
 *@return 轉(zhuǎn)換后的經(jīng)緯度坐標
 */
UIKIT_EXTERN CLLocationCoordinate2D BMKCoordinateForMapPoint(BMKMapPoint mapPoint);

這里有一個問題:以一個城市為例,在百度地圖16、17、18、19等縮放級別下都可以繪制這個城市,但在16、17、18、19級別下畫出來的手繪圖的尺寸(像素)肯定是不一樣的!那么百度地圖的直角坐標是以什么為標準呢?

  • 以百度地圖18級縮放級別為模板繪出的手繪圖,其與百度地圖的直角地理坐標是1:1的關(guān)系(zoomRate)
  • 你可以在百度地圖上找一條直線,看這條直線在16、17、18、19級下長度分別是多少,然后以18級的長度為基準,可以計算出每個縮放等級下的比例值(zoomRate)

所以,如果確定某個經(jīng)緯度點肯定在當前手繪圖中,則可以利用如下公式將經(jīng)緯度坐標轉(zhuǎn)換成手繪圖的平面坐標

// 如果手繪圖是以百度地圖18級為參照畫出來的,則zoomRate為1
#define zoomRate            1

// 手繪圖左上角點的經(jīng)緯度坐標轉(zhuǎn)換成百度地圖的直角坐標
BMKMapPoint leftTopCoor = BMKMapPointForCoordinate(CLLocationCoordinate2DMake(lat, lng))

/**
 * 將經(jīng)緯度坐標轉(zhuǎn)換成手繪圖的平面(像素)坐標
 */
- (CGPoint)locationCoordToCgPoint:(CLLocationCoordinate2D)coor
{
    BMKMapPoint point = BMKMapPointForCoordinate(coor);
    return CGPointMake((point.x - leftTopCoor.x) * zoomRate, (point.y - leftTopCoor.y) * zoomRate);
}

/**
 * 將手繪圖的平面(像素)坐標轉(zhuǎn)換成經(jīng)緯度坐標
 */
- (CLLocationCoordinate2D)cgPointToLocationCoord:(CGPoint)point
{
    BMKMapPoint mapPoint;
    mapPoint.x = point.x / zoomRate + leftTopCoor.x;
    mapPoint.y = point.y / zoomRate + leftTopCoor.y;
    return BMKCoordinateForMapPoint(mapPoint);
}
判斷給定經(jīng)緯度是否在當前手繪圖視野范圍內(nèi)
// 其中imageWidth、imageHeight為手繪圖的像素大?。╬x單位)
- (BOOL)isLocationInImage:(CLLocationCoordinate2D)coor
{
    CGPoint point = [self locationCoordToCgPoint:coor];
    return !(point.x < 0 || point.y < 0 || point.x > imageWidth || point.y > imageHeight);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容