2024-04-17坐标系之间的转换

坐标系之间的转换

最近在做地图展示,同样的经纬度,在不同的地图上位置不一致,为什么要地图偏移,四个字,为了安全,我们从不同的渠道获取到的经纬度信息可能并不是在同一个坐标系下,以下是几个常见坐标系

  • 高德地图、腾讯地图以及谷歌中国区地图使用的是GCJ-02坐标系
  • 百度地图使用的是BD-09坐标系
  • 天地图使用的是CGCS2000坐标系,这是一个地心坐标系,与WGS84坐标系相差不大
  • 底层接口(HTML5 Geolocation或ios、安卓API)通过GPS设备获取的坐标使用的是WGS-84坐标系

踩坑:

在uniapp中调用三方地图,环境不同,所用坐标系也不同,在自定义基座调试时没问题,上线出现偏移,原来问题出在坐标系上,在自定义基座百度默认使用GCJ-02坐标系,上线后使用BD-09坐标系。

function initMap(){
    let that = this;
    var point = {
        longitude: that.location.point.longitude, latitude: that.location.point.latitude
    }
    // 获取当前窗口
    const currentWebview = that.$mp.page.$getAppWebview();
    that.Map = plus.maps.create('map', {
        width: '100%',
        height: '80%',
        center: new plus.maps.Point(point.longitude, point.latitude),
        zoom: 19
    });
    currentWebview.append(that.Map);

    // 地图状态变化 (设置中心点便能触发状态,以此来绘点、获取数据,避免重复调用产生屏幕闪烁)
    that.Map.onstatuschanged = (evt) => {
        let _point = evt.center;
        // 这里自定义基座时为gjc02坐标 打包上线后为百度坐标 所以不需要转换变动
        // 反向地理编码 将坐标点转换为地理位置信息
        plus.maps.Map.reverseGeocode(_point, {
            coordType: 'gcj02'
        }, (res) => {
            that.location = {
                point: res.coord,
                address: res.address
            };
        }, (err) => {
            plus.nativeUI.toast(JSON.stringify(err));
        });
    };
}
GPS定位偏移

定位误差大,且规律明显的情况下可手动纠偏,同一地点,获取到定位经纬度和实际经纬度,进行两点之间距离的偏差计算

uni.getLocation({
    type: 'wgs84',
    success(point) {
    },
    fail(err) {
        plus.nativeUI.toast('读取当前地理位置失败');
    }
});

转换方法

国测局坐标转百度
function gcj02ToBaiDu(mars_point) {
    var x_pi = (3.14159265358979324 * 3000.0) / 180.0
    var baidu_point = {
        longitude: 0,
        latitude: 0,
    };
    var x = mars_point.longitude;
    var y = mars_point.latitude;
    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);
    baidu_point.longitude = z * Math.cos(theta) + 0.0065;
    baidu_point.latitude = z * Math.sin(theta) + 0.006;
    return baidu_point;
}
百度转国测局
bd09ToGcj02(lnglat) {
    var X_PI = (3.14159265358979324 * 3000.0) / 180.0
    var x = lnglat.longitude - 0.0065;
    var y = lnglat.latitude - 0.006;
    var magic = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
    var sqrtMagic = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);
    var mgLng = sqrtMagic * Math.cos(magic);
    var mgLat = sqrtMagic * Math.sin(magic);
    return {
        longitude: mgLng,
        latitude: mgLat
    }
}
wgs84转国测局
function wgs84Togcj02(lng, lat) {
  if (this.out_of_china(lng, lat)) {
    return [lng, lat];
  }
  var that = this;
  const x_PI = (3.14159265358979324 * 3000.0) / 180.0;
  const PI = 3.1415926535897932384626;
  const a = 6378245.0;
  const ee = 0.00669342162296594323;
  let dlat = that.transformlat(lng - 105.0, lat - 35.0);
  let dlng = that.transformlng(lng - 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);
  dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI);
  var mglat = lat + dlat;
  var mglng = lng + dlng;
  return [mglng, mglat];
}

function out_of_china(lng, lat) {
  return (
    lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271 || false
  );
}

function transformlat(lng, lat) {
  const x_PI = (3.14159265358979324 * 3000.0) / 180.0;
  const PI = 3.1415926535897932384626;
  const a = 6378245.0;
  const ee = 0.00669342162296594323;
  let ret =
    -100.0 +
    2.0 * lng +
    3.0 * lat +
    0.2 * lat * lat +
    0.1 * lng * lat +
    0.2 * Math.sqrt(Math.abs(lng));
  ret +=
    ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
      2.0) /
    3.0;
  ret +=
    ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) *
      2.0) /
    3.0;
  ret +=
    ((160.0 * Math.sin((lat / 12.0) * PI) +
      320 * Math.sin((lat * PI) / 30.0)) *
      2.0) /
    3.0;
  return ret;
}
function transformlng(lng, lat) {
  const x_PI = (3.14159265358979324 * 3000.0) / 180.0;
  const PI = 3.1415926535897932384626;
  const a = 6378245.0;
  const ee = 0.00669342162296594323;
  let ret =
    300.0 +
    lng +
    2.0 * lat +
    0.1 * lng * lng +
    0.1 * lng * lat +
    0.1 * Math.sqrt(Math.abs(lng));
  ret +=
    ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
      2.0) /
    3.0;
  ret +=
    ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) *
      2.0) /
    3.0;
  ret +=
    ((150.0 * Math.sin((lng / 12.0) * PI) +
      300.0 * Math.sin((lng / 30.0) * PI)) *
      2.0) /
    3.0;
  return ret;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值