美文网首页
国内地图坐标系介绍及常见地图(百度、高德、凯立德)之间的坐标系

国内地图坐标系介绍及常见地图(百度、高德、凯立德)之间的坐标系

作者: Jackson_Z | 来源:发表于2016-12-10 10:00 被阅读1022次

    一、国内地图坐标系简介

    1、 WGS84(地图坐标)

    美国GPS使用的是WGS84的坐标系统。GPS系统获得的坐标系统,基本为标准的国际通用的WGS84坐标系统

    2、 GCJ-02(火星坐标)

    GCJ-02是由中国国家测绘局制订的地理信息系统的坐标系统。它是一种对经纬度数据的加密算法,即加入随机的偏差。国内出版的各种地图系统(包括电子形式),出于国家安全考虑,必须至少采用GCJ-02对地理位置进行首次加密。
    所有的电子地图所有的导航设备,都需要加入国家保密插件。第一步,地图公司测绘地图,测绘完成后,送到国家测绘局,将真实坐标的电子地图,加密成“火星坐标”,这样的地图才是可以出版和发布的,然后才可以让GPS公司处理。第二步,所有的GPS公司,只要需要汽车导航的,需要用到导航电子地图的,统统需要在软件中加入国家保密算法,将COM口读出来的真实的坐标信号,加密转换成国家要求的保密的坐标,这样,GPS导航仪和导航电子地图就可以完全匹配,GPS也就可以正常工作。
    在国内发行的地图都使用GCJ02进行首次加密,

    地图 坐标系
    百度地图 百度坐标(BD-09
    腾讯搜搜地图 火星坐标
    图吧MapBar地图 图吧坐标
    高德MapABC地图API 火星坐标
    凯立德地图 火星坐标(转为K码

    I、 百度坐标:在GCJ02基础上,进行了BD-09二次加密措施,API支持从WGS/GCJ转换成百度坐标,不支持反转。

    II、凯立德K码:

    • a) K码将地图分成了四块进行编码,中心点在内蒙的阿拉善左旗境内,该点的K码是7uy1yuy1y。以该点为中心分别在东西方向和南北方向画一条线当横纵(XY)坐标轴,那么第一象限(即东北方向的那块)的K码的第1位全部都是5,第2象限的K码的第一位全是6,第3、4象限的K码的第一位分别全是7、8。并且该点有4个K码,即用四个K码定位都是这一点,这四个K码分别是7uy1yuy1y、80000uy1y、500000000、6uy1y0000。

    • b) K码的第2-5位表示东西方向上的坐标,第6-9位代表南北方向上的坐标。实际上K码就是一个凯立德特有的34进制数,(26个字母加10个阿拉伯数字,再去掉不用的小写L和O共34个字符),这个34进制数从左向右从低位向高位排列(我们常用的10进制是从右向左由低位向高位排列),其中第2-5位东西方向上的数每一个单位代表2.5m左右,南北方向上的数每一个单位代表实际距离3米左右。比如80000uy1y向东约2.5米的点的K码就是81000uy1y,向东约34×2.5m的点的K码就是80100uy1y

    • c)K码与火星坐标可相互转换。

    二、坐标系转换

    1、地球坐标系(WGS)到火星坐标系(GCJ-02)的转换算法

    var M_PI = 3.14159265358979324;  
    var a = 6378245.0;  
    var ee = 0.00669342162296594323;  
    var x_pi = M_PI * 3000.0 / 180.0;  
    function out_of_china(lat,  lon) {  
        if (lon < 72.004 || lon > 137.8347)  
            return true;  
        if (lat < 0.8293 || lat > 55.8271)  
            return true;  
        return false;  
    }  
    function wgs2gcj_lat(x, y) {  
        var ret1 = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y  + 0.2 * Math.sqrt(Math.abs(x));  
        ret1 += (20.0 * Math.sin(6.0 * x * M_PI) + 20.0 * Math.sin(2.0 * x  * M_PI)) * 2.0 / 3.0;  
        ret1 += (20.0 * Math.sin(y * M_PI) + 40.0 * Math.sin(y / 3.0 * M_PI)) * 2.0 / 3.0;  
        ret1 += (160.0 * Math.sin(y / 12.0 * M_PI) + 320 * Math.sin(y * M_PI  / 30.0)) * 2.0 / 3.0;  
        return ret1;  
    }  
    function wgs2gcj_lng(x, y) {  
        var ret2 = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1  * Math.sqrt(Math.abs(x));  
        ret2 += (20.0 * Math.sin(6.0 * x * M_PI) + 20.0 * Math.sin(2.0 * x  * M_PI)) * 2.0 / 3.0;  
        ret2 += (20.0 * Math.sin(x * M_PI) + 40.0 * Math.sin(x / 3.0 * M_PI)) * 2.0 / 3.0;  
        ret2 += (150.0 * Math.sin(x / 12.0 * M_PI) + 300.0 * Math.sin(x / 30.0  * M_PI)) * 2.0 / 3.0;  
        return ret2;  
    }  
    function wgs2gcj(poi) {  
        if (out_of_china(poi.lat, poi.lng)) {  
            return poi;  
        }  
        var poi2 = {};  
        var dLat = wgs2gcj_lat(poi.lng - 105.0, poi.lat - 35.0);  
        var dLon = wgs2gcj_lng(poi.lng - 105.0, poi.lat - 35.0);  
        var radLat = poi.lat / 180.0 * M_PI;  
        var magic = Math.sin(radLat);  
        magic = 1 - ee * magic * magic;  
        var sqrtMagic = Math.sqrt(magic);  
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * M_PI);  
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * M_PI);  
        poi2.lat = poi.lat + dLat;  
        poi2.lng = poi.lng + dLon;  
        return poi2;  
    }
    

    2、火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法

    // 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法  
    function gcj2bd(poi) {  
        var poi2 = {};  
        var x = poi.lng, y = poi.lat;  
        var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);  
        var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);  
        poi2.lng = z * Math.cos(theta) + 0.0065;  
        poi2.lat = z * Math.sin(theta) + 0.006;  
        return poi2;  
    }  
    function bd2gcj(poi) {  
        var poi2 = {};  
        var x = poi.lng - 0.0065, y = poi.lat - 0.006;  
        var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);  
        var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);  
        poi2.lng = z * Math.cos(theta);  
        poi2.lat = z * Math.sin(theta);  
        return poi2;  
    } 
    

    3、火星坐标系 (GCJ-02) 与凯立德K码 的转换算法

    var codes = "0123456789abcdefghijkmnpqrstuvwxyz";  
    function __decode(pch)  {  
        var v = 0;  
        for (var i = 3; i >= 0; --i)  
            v = v * 34 + (codes.indexOf(pch.charAt(i)));  
            v = v * 250 / 9;  
        return v;  
    }  
      
    function __encode(v)  {  
        var pch = "";  
        v = v * 9 / 250;  
        for (var i = 0; i < 4; ++i)  {  
            pch += codes.charAt(v % 34);  
            v /= 34;  
        }  
        return pch;  
    }  
      
    function DecodeLon(k)  {  
        var lon = __decode(k.substring(1, 5));  
        if (k.charAt(0) == '5' || k.charAt(0) == '8')  
            lon += 35000000;  
            lon += 70000000;  
        return lon/1000000.0;  
    }  
      
    function DecodeLat(k)  {  
        var lat = __decode(k.substring(5, 9));  
        if (k.charAt(0) <= '6')  
            lat += 35000000;  
            lat += 5000000;  
        return lat/1000000.0;  
    }  
      
    function Encode(lat, lon)  {  
        lat = parseInt(lat*1000000);  
        lon = parseInt(lon*1000000);  
        var k;  
        lon -= 70000000;  
        lat -= 5000000;  
        if (lat > 35000000)  
            if (lon <= 35000000)  
                k = "6";  
            else  
                k = "5";  
        else  
            if (lon <= 35000000)  
                k = "7";  
            else  
                k = "8";  
        if (lon > 35000000)  
            lon -= 35000000;  
        if (lat > 35000000)  
            lat -= 35000000;  
        k += __encode(lon);  
        k += __encode(lat);  
        return k;  
    }  
    

    软件开发程序员博客文章收藏网
    原文

    GCJ-02转换BD-09 : Google地图经纬度转百度地图经纬度

    BD-09转换GCJ-02 : 百度转Google

    WGS-84到GCJ-02 : 即GPS 加偏

    主要就是Google地图,百度地图,GPS经纬度偏移转换

    /**
     * 用于构造地图中的坐标点
     * @author lw
     * **/
    public class Point {
        
        private double lat;// 纬度
        private double lng;// 经度
        
        public Point() {
        }
        
        public Point(double lng, double lat) {
            this.lng = lng;
            this.lat = lat;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof Point) {
                Point bmapPoint = (Point) obj;
                return (bmapPoint.getLng() == lng && bmapPoint.getLat() == lat) ? true : false;
            } else {
                return false;
            }
        }
        
        public double getLat() {
            return lat;
        }
        public void setLat(double lat) {
            this.lat = lat;
        }
        public double getLng() {
            return lng;
        }
        public void setLng(double lng) {
            this.lng = lng;
        }
        
        @Override
        public String toString() {
            return "Point [lat=" + lat + ", lng=" + lng + "]";
        }
        
    }
    
    /**
     * 地图坐标转换 google,baidu,gps
     * @author lw
     * @Time 2015年4月16日18:19:16
     * 
     * */
    public class CoordinateConversion {
        private static final double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        
        private static final double pi = 3.14159265358979324;
        private static final double a = 6378245.0;
        private static final double ee = 0.00669342162296594323;
        
        /**
         * gg_lat 纬度
         * gg_lon 经度
         * GCJ-02转换BD-09
         * Google地图经纬度转百度地图经纬度
         * */
        public static Point google_bd_encrypt(double gg_lat, double gg_lon){
            Point point=new Point();
            double x = gg_lon, y = gg_lat;
            double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
            double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi); 
            double bd_lon = z * Math.cos(theta) + 0.0065;
            double bd_lat = z * Math.sin(theta) + 0.006;
            point.setLat(bd_lat);
            point.setLng(bd_lon);
            return point;
        }
        
        /**
         * wgLat 纬度
         * wgLon 经度
         * BD-09转换GCJ-02
         * 百度转google
         * */
        public static Point bd_google_encrypt(double bd_lat, double bd_lon){
            Point point=new Point();
            double x = bd_lon - 0.0065, y = bd_lat - 0.006;  
            double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);  
            double theta =Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);  
            double gg_lon = z * Math.cos(theta);  
            double gg_lat = z * Math.sin(theta);  
            point.setLat(gg_lat);
            point.setLng(gg_lon);
            return point;
        }
        
        
        
        /**
         * wgLat 纬度
         * wgLon 经度
         * WGS-84 到 GCJ-02 的转换(即 GPS 加偏)
         * */
        public static Point wgs_gcj_encrypts(double wgLat, double wgLon) {
            Point point=new Point();
            if (outOfChina(wgLat, wgLon)) {
                point.setLat(wgLat);
                point.setLng(wgLon);
                return point;
            }
            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);
            double lat = wgLat + dLat;
            double lon = wgLon + dLon;
            point.setLat(lat);
            point.setLng(lon);
            return point;
        }
        
        
        public static void transform(double wgLat, double wgLon, double[] latlng) {
            if (outOfChina(wgLat, wgLon)) {
                latlng[0] = wgLat;
                latlng[1] = wgLon;
                return;
            }
            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);
            latlng[0] = wgLat + dLat;
            latlng[1] = wgLon + dLon;
        }
    
        private static boolean 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;
        }
    }
    

    Google地图百度地图GPS经纬度偏移转换(JAVA)

    相关文章

      网友评论

          本文标题: 国内地图坐标系介绍及常见地图(百度、高德、凯立德)之间的坐标系

          本文链接:https://www.haomeiwen.com/subject/jowymttx.html