具本人研究所知,Mapbar地图的成图算法并不难懂,并且它的地图成图算法没有进行加密(效果就是整个地图有一定的偏移,实际上它的成图是准确的),由此可想而知,它的坐标必定也未加密!

那么为什么我用真实的经纬坐标在Mapbar上标注的时候,会有明显的偏移呢?

在我们应用Mapbar开发一些应用的时候,我们所看到的或者是获取到的经纬度坐标其实都不是真正的地理坐标,而是经过Mapbar加密以后的坐标,所以对于外来的坐标Mapbar并不感冒。

在Mapbar的Api中,它会对传入的坐标进行一次解密(会获得真实的经纬度坐标),然后在Api的核心成图函数里就使用这个真实的坐标绘制用户可见的地图,而我们通过API获取的Mapbar坐标都是加密以后的坐标。

综上,如果你传给了Mapbar一个真实的坐标,因为它会对所有传入的坐标进行一次解密,因为我们传的本来就是真实的坐标,被它这么一解密反而就不真实了,于是这个不真实的坐标在后面成图中以及标注点上就有了偏移。

废话太多了,直接看代码吧!

经纬度加密算法如下:(PHP版)

/**
 * 将真实地理坐标加密为Mapbar经纬度坐标
 *
 * @param $x 经度值
 * @param $y 维度值
 * @returns array
 */
function coordOffsetEncrypt($x,$y){
    $x = floatval($x)*100000%36000000;
    $y = floatval($y)*100000%36000000;

    $_X = intval(((cos($y/100000))*($x/18000))+((sin($x/100000))*($y/9000))+$x);
    $_Y = intval(((sin($y/100000))*($x/18000))+((cos($x/100000))*($y/9000))+$y);

    return array($_X/100000.0,$_Y/100000.0);
}

经纬坐标加密算法(Javascript版)

/**
 * 将真实地理坐标加密为Mapbar经纬度坐标
 *
 * @param x 经度值
 * @param y 维度值
 * @returns [x,y]
 */
function coordOffsetEncrypt(x, y) {
    var x = parseFloat(x) * 100000 % 36000000;
    var y = parseFloat(y) * 100000 % 36000000;

    var _x = parseFloat(((Math.cos(y / 100000)) * (x / 18000)) + ((Math.sin(x / 100000)) * (y / 9000)) + x);
    var _y = parseFloat(((Math.sin(y / 100000)) * (x / 18000)) + ((Math.cos(x / 100000))*(y/9000))+y);

    return [_x / 100000.0, _y / 100000.0];
}

经纬度坐标解密算法(PHP版)

/**
 * 将Mapbar经纬坐标解密为真实地理坐标
 *
 * @param $x 经度值
 * @param $y 维度值
 * @returns array
 */
function croodOffsetDecrypt($x,$y){
    $x = floatval($x)*100000%36000000;
    $y = floatval($y)*100000%36000000;

    $x1 = intval(-(((cos($y/100000))*($x/18000))+((sin($x/100000))*($y/9000)))+$x);
    $y1 = intval(-(((sin($y/100000))*($x/18000))+((cos($x/100000))*($y/9000)))+$y);

    $x2 = intval(-(((cos($y1/100000))*($x1/18000))+((sin($x1/100000))*($y1/9000)))+$x+(($x>0)?1:-1));
    $y2 = intval(-(((sin($y1/100000))*($x1/18000))+((cos($x1/100000))*($y1/9000)))+$y+(($y>0)?1:-1));

    return array($x2/100000.0,$y2/100000.0);
}

经纬度坐标解密算法(Javascript版)

/**
 * 将Mapbar经纬坐标解密为真实地理坐标
 *
 * @param x 经度值
 * @param y 维度值
 * @returns [x,y]
 */
function croodOffsetDecrypt(x, y){
    var x = parseFloat(x) * 100000 % 36000000;
    var y = parseFloat(y) * 100000 % 36000000;

    var x1 = parseInt(-(((Math.cos(y / 100000)) * (x / 18000)) + ((Math.sin(x / 100000)) * (y / 9000))) + x);
    var y1 = parseInt(-(((Math.sin(y / 100000)) * (x / 18000)) + ((Math.cos(x / 100000)) * (y / 9000))) + y);

    var x2 = parseInt(-(((Math.cos(y1 / 100000)) * (x1 / 18000)) + ((Math.sin(x1 / 100000)) * (y1 / 9000))) + x + ((x > 0) ? 1 : -1));
    var y2 = parseInt(-(((Math.sin(y1 / 100000))  *(x1 / 18000)) + ((Math.cos(x1 / 100000)) * (y1 / 9000))) + y + ((y > 0) ? 1 : -1));

    return [x2 / 100000.0, y2 / 100000.0];
}

演示