坐标转换工具类:84坐标系,火星坐标系,与百度坐标系之间的互相转换

开发中经常会遇到坐标系之间互相转换的需求,下面分享一个坐标转化工具类:


public class GpsTransformUtil {

    /**
     * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
     * 即 百度 转 谷歌、高德
     *
     * @param bdLon
     * @param bdLat
     * @return Double[lon, lat]
     */
    public static Double[] BD09ToGCJ02(Double bdLon, Double bdLat) {
        double x = bdLon - 0.0065;
        double y = bdLat - 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[] arr = new Double[2];
        arr[0] = z * Math.cos(theta);
        arr[1] = z * Math.sin(theta);
        return arr;
    }

    /**
     * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
     * 即谷歌、高德 转 百度
     *
     * @param gcjLon
     * @param gcjLat
     * @return Double[lon, lat]
     */
    public static Double[] GCJ02ToBD09(Double gcjLon, Double gcjLat) {
        double z = Math.sqrt(gcjLon * gcjLon + gcjLat * gcjLat) + 0.00002 * Math.sin(gcjLat * x_PI);
        double theta = Math.atan2(gcjLat, gcjLon) + 0.000003 * Math.cos(gcjLon * x_PI);
        Double[] arr = new Double[2];
        arr[0] = z * Math.cos(theta) + 0.0065;
        arr[1] = z * Math.sin(theta) + 0.006;
        return arr;
    }

    /**
     * WGS84转GCJ02(火星坐标系)
     *
     * @param wgsLon
     * @param wgsLat
     * @return Double[lon, lat]
     */
    public static Double[] WGS84ToGCJ02(Double wgsLon, Double wgsLat) {
        if (outOfChina(wgsLon, wgsLat)) {
            return new Double[]{wgsLon, wgsLat};
        }
        double dlat = transformLatitude(wgsLon - 105.0, wgsLat - 35.0);
        double dlng = transformLongitude(wgsLon - 105.0, wgsLat - 35.0);
        double radLat = wgsLat / 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);
        dlng = (dlng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
        Double[] arr = new Double[2];
        arr[0] = wgsLon + dlng;
        arr[1] = wgsLat + dlat;
        return arr;
    }

    /**
     * GCJ02转WGS84
     *
     * @param gcjLon
     * @param gcjLat
     * @return Double[lon, lat]
     */
    public static Double[] GCJ02ToWGS84(Double gcjLon, Double gcjLat) {
        if (outOfChina(gcjLon, gcjLat)) {
            return new Double[]{gcjLon, gcjLat};
        }
        double dlat = transformLatitude(gcjLon - 105.0, gcjLat - 35.0);
        double dlng = transformLongitude(gcjLon - 105.0, gcjLat - 35.0);
        double radLat = gcjLat / 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);
        dlng = (dlng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
        double mgLat = gcjLat + dlat;
        double mgLng = gcjLon + dlng;
        return new Double[]{gcjLon * 2 - mgLng, gcjLat * 2 - mgLat};
    }

    /**
     * WGS84=>GCJ02 地球坐标系=>火星坐标系
     *
     * @param lng 经度
     * @param lat 纬度
     * @return 转化结果
     */
    public static Double[] wgs84ToGcj02(double lng, double lat) {
        if (outOfChina(lng, lat)) {
            return new Double[]{lng, lat};
        }

        double[] offset = offset(lng, lat);
        double mglng = lng + offset[0];
        double mglat = lat + offset[1];

        return new Double[]{mglng, mglat};
    }

    /**
     * GCJ02=>WGS84[精确]
     *
     * @param lng       经度
     * @param lat       纬度
     * @param threshold 精度
     * @return Double[lon, lat]
     */
    public static Double[] gcj02ToWgs84Exactly(double lng, double lat, Double threshold) {
        if (outOfChina(lng, lat)) {
            return new Double[]{lng, lat};
        }

        double initDelta = 0.01;
        threshold = Optional.ofNullable(threshold).orElse(0.000000001);
        double dLat = initDelta, dLon = initDelta;
        double mLat = lat - dLat, mLon = lng - dLon;
        double pLat = lat + dLat, pLon = lng + dLon;
        double wgsLat, wgsLng, i = 0;
        while (true) {
            wgsLat = (mLat + pLat) / 2;
            wgsLng = (mLon + pLon) / 2;
            Double[] wgs84ToGcj02 = wgs84ToGcj02(wgsLng, wgsLat);
            dLon = wgs84ToGcj02[0] - lng;
            dLat = wgs84ToGcj02[1] - lat;
            if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold)) {
                break;
            }

            if (dLat > 0) {
                pLat = wgsLat;
            } else {
                mLat = wgsLat;
            }
            if (dLon > 0) {
                pLon = wgsLng;
            } else {
                mLon = wgsLng;
            }

            if (++i > 10000) {
                break;
            }
        }

        return new Double[]{wgsLng, wgsLat};
    }
}

拿去不谢,欢迎评论区交流,点赞收藏。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TheChainsmoker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值