手绘图导航

简介

通常在项目中需要用到地图的时候我们会选择百度、高德等地图;但有的时候客户会要求提供基于手绘图的定位、导游导览功能,百度-瓦片图层、高德-图片覆盖物提供了相应的解决方案,我们可以把手绘图作为瓦片、覆盖物放在地图上,但是这种方案有其局限性:必须依托百度、高德地图本身才能查看手绘图。

接下来我将为大家带来另外一种解决方案,纯手绘图导游导览、定位,先看效果图:

手绘图导游导览

NAMapKit

NAMapKit是一个开源的手绘图框架,支持缩放、地图标记、高清地图切片浏览、本地手绘图、在线手绘图功能。

NAMapKit Demo

Popup Menu

默认情况下NAMapKit的标记点弹出框不够nice,所以我在github上fork了NAMapKit,并实现了与City Guides by National Geographic这款App中类似的功能:

Fork NAMapKit on github

标记点

普通点标记

普通点的标记可以直接用尺子在手绘图上量一下,拿到目标点的CGPoint(x,y),之后把这个point作为NAPinAnnotation添加到地图上,这样就实现了打点的功能。

当前位置打点

要实现当前位置打点,就得将经纬度坐标转换成图片的平面坐标,以百度地图来说,它提供了以下转换函数:

// BMKGeometry.h
/**
 *将经纬度坐标转换为投影后的直角地理坐标
 *@param coordinate 待转换的经纬度坐标
 *@return 转换后的直角地理坐标
 */
UIKIT_EXTERN BMKMapPoint BMKMapPointForCoordinate(CLLocationCoordinate2D coordinate);

/**
 *将投影后的直角地理坐标转换为经纬度坐标
 *@param mapPoint 投影后的直角地理坐标
 *@return 转换后的经纬度坐标
 */
UIKIT_EXTERN CLLocationCoordinate2D BMKCoordinateForMapPoint(BMKMapPoint mapPoint);

这里有一个问题:以一个城市为例,在百度地图16、17、18、19等缩放级别下都可以绘制这个城市,但在16、17、18、19级别下画出来的手绘图的尺寸(像素)肯定是不一样的!那么百度地图的直角坐标是以什么为标准呢?

  • 以百度地图18级缩放级别为模板绘出的手绘图,其与百度地图的直角地理坐标是1:1的关系(zoomRate)
  • 你可以在百度地图上找一条直线,看这条直线在16、17、18、19级下长度分别是多少,然后以18级的长度为基准,可以计算出每个缩放等级下的比例值(zoomRate)

所以,如果确定某个经纬度点肯定在当前手绘图中,则可以利用如下公式将经纬度坐标转换成手绘图的平面坐标

// 如果手绘图是以百度地图18级为参照画出来的,则zoomRate为1
#define zoomRate            1

// 手绘图左上角点的经纬度坐标转换成百度地图的直角坐标
BMKMapPoint leftTopCoor = BMKMapPointForCoordinate(CLLocationCoordinate2DMake(lat, lng))

/**
 * 将经纬度坐标转换成手绘图的平面(像素)坐标
 */
- (CGPoint)locationCoordToCgPoint:(CLLocationCoordinate2D)coor
{
    BMKMapPoint point = BMKMapPointForCoordinate(coor);
    return CGPointMake((point.x - leftTopCoor.x) * zoomRate, (point.y - leftTopCoor.y) * zoomRate);
}

/**
 * 将手绘图的平面(像素)坐标转换成经纬度坐标
 */
- (CLLocationCoordinate2D)cgPointToLocationCoord:(CGPoint)point
{
    BMKMapPoint mapPoint;
    mapPoint.x = point.x / zoomRate + leftTopCoor.x;
    mapPoint.y = point.y / zoomRate + leftTopCoor.y;
    return BMKCoordinateForMapPoint(mapPoint);
}
判断给定经纬度是否在当前手绘图视野范围内
// 其中imageWidth、imageHeight为手绘图的像素大小(px单位)
- (BOOL)isLocationInImage:(CLLocationCoordinate2D)coor
{
    CGPoint point = [self locationCoordToCgPoint:coor];
    return !(point.x < 0 || point.y < 0 || point.x > imageWidth || point.y > imageHeight);
}

你可能感兴趣的:(手绘图导航)