首页 > 代码库 > 无意中发现了谷歌、腾讯、高德地图纠偏算法

无意中发现了谷歌、腾讯、高德地图纠偏算法

大家知道,天朝的地图都是加偏的,也就是GPS设备接收到的坐标和电子地图坐标是不一样的,有一定的偏移,如果直接把GPS坐标显示到电子地图上,有几百米的误差,必须把GPS坐标加上一定的偏移再显示到电子地图上,才和实际相符,理论上,每种地图偏移量不一样的,且都不是线性的,供应商提供在线的接口,把GPS坐标转换成地图坐标,但算法是保密的,我们可以自己创建纠偏库(参见百度谷歌等地图纠偏库),但部分地方不使用数据库,也不适合网上调用,最合适的办法就是通过算法直接计算,我在网上无意看到了用java写的谷歌地图纠偏算法,稍作修改,变成C#的了,测试了一下,居然腾讯/高德地图纠偏算法也是完全一样,因此,有了该算法,再也不用为纠偏发愁了,不知道该算法是否有泄密的嫌疑,我也是网上抄的,解决了谷歌、腾讯、高德地图纠偏问题,虽然谷歌地图已经谈出视野了。

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;


namespace PostionOffsetCreate
{
    public class GDMapOffset
    {
        private static double pi = 3.14159265358979324;
        private static double a = 6378245.0;
        private static double ee = 0.00669342162296594323;


        public static Point transform(int p_Lng,int p_Lat)
        {
            double wgLon = 0.000001 * p_Lng, wgLat = 0.000001 * p_Lat;
            if (outOfChina(wgLat, wgLon))
            {
                return new Point(p_Lng, p_Lat);
            }
            double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
            double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
            double radLat = wgLat / 180.0 * pi;
            double magic = Math.Sin(radLat);
            magic = 1 - ee * magic * magic;
            double sqrtMagic = Math.Sqrt(magic);
            dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
            dLon = (dLon * 180.0) / (a / sqrtMagic * Math.Cos(radLat) * pi);
            return new Point((int)((wgLon + dLon) * 1000000), (int)((wgLat + dLat) * 1000000));
        }


        private static bool outOfChina(double lat, double lon)
        {
            if (lon < 72.004 || lon > 137.8347)
                return true;
            if (lat < 0.8293 || lat > 55.8271)
                return true;
            return false;
        }


        private static double transformLat(double x, double y)
        {
            double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.Sqrt(Math.Abs(x));
            ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.Sin(y * pi) + 40.0 * Math.Sin(y / 3.0 * pi)) * 2.0 / 3.0;
            ret += (160.0 * Math.Sin(y / 12.0 * pi) + 320 * Math.Sin(y * pi / 30.0)) * 2.0 / 3.0;
            return ret;
        }


        private static double transformLon(double x, double y)
        {
            double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.Sqrt(Math.Abs(x));
            ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.Sin(x * pi) + 40.0 * Math.Sin(x / 3.0 * pi)) * 2.0 / 3.0;
            ret += (150.0 * Math.Sin(x / 12.0 * pi) + 300.0 * Math.Sin(x / 30.0 * pi)) * 2.0 / 3.0;
            return ret;
        }
    }
}

坐标经纬度均用百万方分之一度表示,返回Point类型,X代表经度,Y代表纬度,即传入GPS坐标,得到地图坐标,如:

Point pt=PostionOffsetCreate. Point transform(120123456,28123456);