java常用坐标系转换

常用 bd09、wgs84、gcj02 以及广州2000 坐标系互转

/**
 * 坐标转换
 *
 * @author maofs
 * @version 1.0
 * @date 2021 -04-26 11:45:13
 */
public interface ICoordTransformService {
    /**
     * The constant x_PI.
     */
    Double XPI = 3.14159265358979324 * 3000.0 / 180.0;

    /**
     * The constant PI.
     */
    Double PI = 3.1415926535897932384626;

    /**
     * The constant a.
     */
    Double A = 6378245.0;

    /**
     * The constant ee.
     */
    Double EE = 0.00669342162296594323;


    /**
     * The constant T2345_TO_GZ2000_X.
     */
    Double T2345_TO_GZ2000_X = -374151.464765618;

    /**
     * The constant T2345_TO_GZ2000_Y.
     */
    Double T2345_TO_GZ2000_Y = -2331890.52174604;

    /**
     * The constant T2345_TO_GZ2000_M.
     */
    Double T2345_TO_GZ2000_M = -3.59216301315524E-06;

    /**
     * The constant T2345_TO_GZ2000_R.
     */
    Double T2345_TO_GZ2000_R = 0.00484909724486718;

    /**
     * The constant GZ2000_TO_2435_X.
     */
    Double GZ2000_TO_2435_X = 385455.970368639;


    /**
     * The constant GZ2000_TO_2435_Y.
     */
    Double GZ2000_TO_2435_Y = 2330057.18710631;

    /**
     * The constant GZ2000_TO_2435_M.
     */
    Double GZ2000_TO_2435_M = 3.58872253802822E-06;


    /**
     * The constant GZ2000_TO_2435_R.
     */
    Double GZ2000_TO_2435_R = -0.00484909724489578;


    /**
     * Bd 09 to gcj 02 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] bd09ToGcj02(Double lng, Double lat);

    /**
     * Bd 09 to wgs 84 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] bd09ToWgs84(Double lng, Double lat);

    /**
     * Bd 09 to gz 2000 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] bd09ToGz2000(Double lng, Double lat);

    /**
     * Gcj 02 to bd 09 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] gcj02ToBd09(Double lng, Double lat);

    /**
     * Gcj 02 to wgs 84 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] gcj02ToWgs84(Double lng, Double lat);

    /**
     * Gcj 02 to gz 2000 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] gcj02ToGz2000(Double lng, Double lat);

    /**
     * Wgs 84 to gcj 02 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] wgs84ToGcj02(Double lng, Double lat);

    /**
     * Wgs 84 to bd 09 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] wgs84ToBd09(Double lng, Double lat);

    /**
     * Wgs 84 to gz 2000 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] wgs84ToGz2000(Double lng, Double lat);

    /**
     * Gz 2000 to wgs 84 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] gz2000ToWgs84(Double lng, Double lat);

    /**
     * Gz 2000 to bd 09 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] gz2000ToBd09(Double lng, Double lat);

    /**
     * Gz 2000 to gcj 02 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    Double[] gz2000ToGcj02(Double lng, Double lat);

    /**
     * Transform lat double.
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double
     */
    default Double transformLat(Double lng, Double lat) {
        lat = +lat;
        lng = +lng;
        double 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;
    }

    /**
     * Transform lng double.
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double
     */
    default Double transformLng(Double lng, Double lat) {
        lat = +lat;
        lng = +lng;
        double 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;
    }

    /**
     * 判断是否在国内,不在国内则不做偏移
     *
     * @param lng the lng
     * @param lat the lat
     * @return the boolean
     */
    default boolean outOfChina(Double lng, Double lat) {
        lat = +lat;
        lng = +lng;
        // 纬度 3.86~53.55, 经度 73.66~135.05 
        return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
    }


    /**
     * Wgs 84 to 2435 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    default Double[] wgs84To2435(Double lng, Double lat) {
        CRSFactory crsFactory = new CRSFactory();
        //源坐标系统
        String sourceCrs = "wgs84";
        String sourceCrsParams = "+proj=longlat +datum=WGS84 +no_defs ";
        CoordinateReferenceSystem source = crsFactory.createFromParameters(sourceCrs, sourceCrsParams);

        //目标坐标系统
        String targetCrs = "2435";
        String targetCrsParams = "+proj=tmerc +lat_0=0 +lon_0=114 +k=1 +x_0=500000 +y_0=0  +towgs84=15.8,-154.4,-82.3 +ellps=krass +units=m +no_defs ";
        CoordinateReferenceSystem target = crsFactory.createFromParameters(targetCrs, targetCrsParams);

        //定义转换类WGS84转2436
        CoordinateTransformFactory ctf = new CoordinateTransformFactory();
        CoordinateTransform transform = ctf.createTransform(source, target);

        //WGS84坐标系转换
        ProjCoordinate projCoordinate = new ProjCoordinate(lng, lat);
        transform.transform(projCoordinate, projCoordinate);
        double x1 = projCoordinate.x;
        double y1 = projCoordinate.y;
        return new Double[]{x1, y1};
    }

    /**
     * Gz 2000 to 2345 double [ ].
     *
     * @param lng the lng
     * @param lat the lat
     * @return the double [ ]
     */
    default Double[] t2435ToWgs84(Double lng, Double lat) {
        CRSFactory crsFactory = new CRSFactory();
        //目标坐标系统
        String targetCrs = "wgs84";
        String targetCrsParams = "+proj=longlat +datum=WGS84 +no_defs ";
        CoordinateReferenceSystem target = crsFactory.createFromParameters(targetCrs, targetCrsParams);

        //源坐标系统
        String sourceCrs = "2435";
        String sourceCrsParams = "+proj=tmerc +lat_0=0 +lon_0=114 +k=1 +x_0=500000 +y_0=0  +towgs84=15.8,-154.4,-82.3 +ellps=krass +units=m +no_defs ";
        CoordinateReferenceSystem source = crsFactory.createFromParameters(sourceCrs, sourceCrsParams);

        //定义转换类2436转WGS84
        CoordinateTransformFactory ctf = new CoordinateTransformFactory();
        CoordinateTransform transform = ctf.createTransform(source, target);

        //WGS84坐标系转换
        ProjCoordinate projCoordinate = new ProjCoordinate(lng, lat);
        transform.transform(projCoordinate, projCoordinate);
        double x1 = projCoordinate.x;
        double y1 = projCoordinate.y;
        return new Double[]{x1, y1};
    }
}
/**
 * 坐标转换
 *
 * @author maofs
 * @version 1.0
 * @date 2021 -04-26 11:45:13
 */
public class CoordTransformServiceImpl implements ICoordTransformService {

    /**
     * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02) 的转换 即 百度 转 谷歌、高德
     *
     * @param bdLng 经度
     * @param bdLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] bd09ToGcj02(Double bdLng, Double bdLat) {
        bdLng = +bdLng;
        bdLat = +bdLat;
        Double x = bdLng - 0.0065;
        Double y = bdLat - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * XPI);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * XPI);
        double gcLng = z * Math.cos(theta);
        double gcLat = z * Math.sin(theta);
        return new Double[]{gcLng, gcLat};
    }

    /**
     * 百度坐标系 (BD-09) 与 WGS-84的转换
     *
     * @param bdLng 经度
     * @param bdLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] bd09ToWgs84(Double bdLng, Double bdLat) {
        Double[] gcDoubles = bd09ToGcj02(bdLng, bdLat);
        return gcj02ToWgs84(gcDoubles[0], gcDoubles[1]);
    }

    /**
     * 百度坐标系 (BD-09) 与 GZ2000的转换
     *
     * @param bdLng 经度
     * @param bdLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] bd09ToGz2000(Double bdLng, Double bdLat) {
        Double[] doubles = bd09ToWgs84(bdLng, bdLat);
        return wgs84ToGz2000(doubles[0], doubles[1]);
    }

    /**
     * WGS-84 转 BD09
     *
     * @param wgLng 经度
     * @param wgLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] wgs84ToBd09(Double wgLng, Double wgLat) {
        Double[] doubles = wgs84ToGcj02(wgLng, wgLat);
        return gcj02ToBd09(doubles[0], doubles[1]);
    }

    /**
     * WGS-84 转 GZ2000
     *
     * @param wgLng 经度
     * @param wgLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] wgs84ToGz2000(Double wgLng, Double wgLat) {
        Double[] doubles = wgs84To2435(wgLng, wgLat);
        Double lng = doubles[0];
        Double lat = doubles[1];
        double x = T2345_TO_GZ2000_X + (1 + T2345_TO_GZ2000_M) * (Math.cos(T2345_TO_GZ2000_R) * lng - Math.sin(T2345_TO_GZ2000_R) * lat);
        double y = T2345_TO_GZ2000_Y + (1 + T2345_TO_GZ2000_M) * (Math.sin(T2345_TO_GZ2000_R) * lng + Math.cos(T2345_TO_GZ2000_R) * lat);
        return new Double[]{x, y};

      /*  CoordDTO coordDTO = null;
        try {
            coordDTO = gz2000ApiService.wsg84ToGz2000(wgLng, wgLat, tokens);
        } catch (Exception e) {
            e.printStackTrace();
            Assert.isTrue(false, e.getMessage());
        }
        
        return new Double[] {coordDTO.getX(), coordDTO.getY()};*/
    }

    /**
     * WGS-84 转 GCJ-02
     *
     * @param wgLng 经度
     * @param wgLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] wgs84ToGcj02(Double wgLng, Double wgLat) {
        double lat = +wgLat;
        double lng = +wgLng;
        if (outOfChina(lng, lat)) {
            return new Double[]{lng, lat};
        } else {
            double dlat = transformLat(lng - 105.0, lat - 35.0);
            double dlng = transformLng(lng - 105.0, lat - 35.0);
            double radLat = lat / 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 gcLat = lat + dlat;
            double gcLng = lng + dlng;
            return new Double[]{gcLng, gcLat};
        }
    }

    /**
     * 火星坐标系 (GCJ-02) 与 BD09 的转换
     *
     * @param gcLng 经度
     * @param gcLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] gcj02ToBd09(Double gcLng, Double gcLat) {
        double lat = +gcLat;
        double lng = +gcLng;
        double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * XPI);
        double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * XPI);
        double bdLng = z * Math.cos(theta) + 0.0065;
        double bdLat = z * Math.sin(theta) + 0.006;
        return new Double[]{bdLng, bdLat};
    }

    /**
     * GCJ-02 转换为 WGS-84
     *
     * @param gcLng 经度
     * @param gcLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] gcj02ToWgs84(Double gcLng, Double gcLat) {
        double lat = +gcLat;
        double lng = +gcLng;
        if (outOfChina(lng, lat)) {
            return new Double[]{lng, lat};
        } else {
            double dlat = transformLat(lng - 105.0, lat - 35.0);
            double dlng = transformLng(lng - 105.0, lat - 35.0);
            double radLat = lat / 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 = lat + dlat;
            double mgLng = lng + dlng;
            return new Double[]{lng * 2 - mgLng, lat * 2 - mgLat};
        }
    }

    /**
     * GCJ-02 转换为 gz2000
     *
     * @param gcLng 经度
     * @param gcLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] gcj02ToGz2000(Double gcLng, Double gcLat) {
        Double[] doubles = gcj02ToWgs84(gcLng, gcLat);
        return wgs84ToGz2000(doubles[0], doubles[1]);
    }

    /**
     * Gz2000 to Wgs84
     *
     * @param gzLng 经度
     * @param gzLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] gz2000ToWgs84(Double gzLng, Double gzLat) {
        double x = GZ2000_TO_2435_X + (1 + GZ2000_TO_2435_M) * (Math.cos(GZ2000_TO_2435_R) * gzLng - Math.sin(GZ2000_TO_2435_R) * gzLat);
        double y = GZ2000_TO_2435_Y + (1 + GZ2000_TO_2435_M) * (Math.sin(GZ2000_TO_2435_R) * gzLng + Math.cos(GZ2000_TO_2435_R) * gzLat);
        return t2435ToWgs84(x, y);
       /* CoordDTO coordDTO = gz2000ApiService.gz2000ToWsg84(gzLng, gzLat, tokens);
        return new Double[]{coordDTO.getX(), coordDTO.getY()};*/
    }

    /**
     * Gz2000 to Wgs84
     *
     * @param gzLng 经度
     * @param gzLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] gz2000ToBd09(Double gzLng, Double gzLat) {
        Double[] doubles = gz2000ToWgs84(gzLng, gzLat);
        return wgs84ToBd09(doubles[0], doubles[1]);
    }

    /**
     * Gz2000 to Gcj02
     *
     * @param gzLng 经度
     * @param gzLat 纬度
     * @return the double [ ]
     */
    @Override
    public Double[] gz2000ToGcj02(Double gzLng, Double gzLat) {
        Double[] doubles = gz2000ToWgs84(gzLng, gzLat);
        return wgs84ToGcj02(doubles[0], doubles[1]);
    }

}

版权声明:本文为weixin_43931248原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。