欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

前端地图坐标系详解

程序员文章站 2022-07-02 08:45:31
...

1.地图类型

国外

国外一般就是GPS,谷歌地图

国内

百度地图,高德地图,腾讯地图,搜狗地图,天地图…

2.坐标系类型

WGS84坐标系

最常见的GPS,用的是WGS-84坐标系,也是原始坐标体系。一般用国际标准的GPS记录仪记录下来的坐标,都是GPS的坐标。

GCJ-02坐标系

国测局02年发布的坐标体系。又称火星坐标系。火星坐标系就是在84坐标系的基础上进行了一次加密偏移所得到的坐标系。在中国,必须至少使用GCJ-02的坐标体系。比如腾讯,高德都在用这个坐标体系。GCJ-02也是国内最广泛使用的坐标体系。

百度BD-09坐标系

国内的地图服务,例如高德地图等等都采用的是火星坐标系,也就是在84坐标系的基础上进行了一次加密后得到的坐标系。而百度这个小伙子干脆直接又自己研发了一套加密算法。所以又复杂了一点。

天地图

天地图采用的是CGCS-2000坐标系(2000坐标系),但是因为CGCS-2000坐标系它与WGS84坐标系都是地心坐标系,因此两者相差不大。况且,考虑到EPSG(地图的一种唯一身份标识),天地图在调用初始化的时候,可以申明天地图采用的坐标系的类型为EPSG:4326,也就是最通用的84坐标系,如下图:

const map = new T.Map(id, { projection: "EPSG:4326" });

各类坐标系坐标点的转换方法

由于不同的地图采用不同的坐标系,因此在不同地图上获取到的点位(经纬度坐标),或者通过不同地图的开放接口获取到的经纬度坐标点,打在不同地图上会有一定程度的偏差,因此就需要坐标转换。

百度坐标火星坐标

var x_pi=3.14159265358979324 * 3000.0 / 180.0;
function baiduTomars(baidu_point){
    var mars_point={lon:0,lat:0};
    var x=baidu_point.lon-0.0065;
    var y=baidu_point.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);
    mars_point.lon=z * Math.cos(theta);
    mars_point.lat=z * Math.sin(theta);
    return mars_point;
}

火星坐标百度坐标

var x_pi=3.14159265358979324 * 3000.0 / 180.0;
function baiduTomars(baidu_point){
    var mars_point={lon:0,lat:0};
    var x=baidu_point.lon-0.0065;
    var y=baidu_point.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);
    mars_point.lon=z * Math.cos(theta);
    mars_point.lat=z * Math.sin(theta);
    return mars_point;
}

84坐标火星坐标

var pi = 3.14159265358979324;
var a = 6378245.0;
var ee = 0.00669342162296594323;
/*判断是否在国内,不在国内则不做偏移*/
function outOfChina(lon, lat)
{
    if ((lon < 72.004 || lon > 137.8347)&&(lat < 0.8293 || lat > 55.8271)){
        return true;
    }else {
        return false;
    }
}
function transformLat(x,y)
{
    var 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;
}

function transformLon(x,y)
{
    var 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;
}

function transform(wgLat,wgLon)
{
    var mars_point={lon:0,lat:0};
    if (outOfChina(wgLat, wgLon))
    {
        mars_point.lat = wgLat;
        mars_point.lon = wgLon;
        return;
    }
    var dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
    var dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
    var radLat = wgLat / 180.0 * 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) * pi);
    dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
    mars_point.lat = wgLat + dLat;
    mars_point.lon = wgLon + dLon;
    return mars_point
}


火星坐标84坐标

var PI = 3.14159265358979324;
function transformGCJ2WGS(gcjLat, gcjLon) {
    let d = delta(gcjLat, gcjLon)
    return {
      'lat': gcjLat - d.lat,
      'lon': gcjLon - d.lon
    }
  }

  function delta(lat, lon) {
    let a = 6378245.0 //  a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
    let ee = 0.00669342162296594323 //  ee: 椭球的偏心率。
    let dLat = transformLat(lon - 105.0, lat - 35.0)
    let dLon = transformLon(lon - 105.0, lat - 35.0)
    let radLat = lat / 180.0 * PI
    let magic = Math.sin(radLat)
    magic = 1 - ee * magic * magic
    let 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 {
      'lat': dLat,
      'lon': dLon
    }
  }
  function transformLat(x, y) {
    let 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
  }
  function transformLon(x, y) {
    let 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
  }


84坐标火星坐标

var x_pi=3.14159265358979324 * 3000.0 / 180.0;
function baiduTomars(baidu_point){
    var mars_point={lon:0,lat:0};
    var x=baidu_point.lon-0.0065;
    var y=baidu_point.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);
    mars_point.lon=z * Math.cos(theta);
    mars_point.lat=z * Math.sin(theta);
    return mars_point;
}

就贴几个常用的,毕竟百度的需要两次转换。以上方法来自:坐标系转换