由GPS定位的经纬度转换成百度地图经纬度坐标

/**
 * @Description: 各地图API坐标系统比较与转换; WGS84坐标系:即地球坐标系,国际上通用的坐标系。设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系,
 *               谷歌地图采用的是WGS84地理坐标系(中国范围除外);
 *               GCJ02坐标系:即火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。
 *               谷歌中国地图和搜搜中国地图采用的是GCJ02地理坐标系; BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系;
 *               搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。
 */
public class GpsUtil {
  public static final String BAIDU_LBS_TYPE = "bd09ll";

  public final static double PI = 3.1415926535897932384626;
  public final static double X_PI = PI * 3000.0 / 180.0;

  /**
   * 地球赤道半径
   */
  public final static double GLOBAL_R = 6371393.0;

  public final static double EE = 0.00669342162296594323;

  /**
   * 国际坐标 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System
   *
   * @param wgsLat 纬度
   * @param wgsLgt 经度
   * @return GpsTranslateDTO
   */
  public static GpsTranslateDTO wgs84ToGcj02(double wgsLat, double wgsLgt) {
    if (outOfChina(wgsLat, wgsLgt)) {
      return null;
    }
    double dLat = transformLat(wgsLgt - 105.0, wgsLat - 35.0);
    double dLon = transformLon(wgsLgt - 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) / ((GLOBAL_R * (1 - EE)) / (magic * sqrtMagic) * PI);
    dLon = (dLon * 180.0) / (GLOBAL_R / sqrtMagic * Math.cos(radLat) * PI);
    double mgLat = wgsLat + dLat;
    double mgLon = wgsLgt + dLon;
    return new GpsTranslateDTO(mgLat, mgLon);
  }

  /**
   * dddmmmmmm格式国际坐标 to 火星坐标系 (GCJ-02)
   *
   * @param wgsLat 纬度
   * @param wgsLgt 经度
   * @return GpsTranslateDTO
   */
  public static GpsTranslateDTO wgs84ToGcj02(int wgsLat, int wgsLgt) {
    return wgs84ToGcj02(changeRad(wgsLat), changeRad(wgsLgt));
  }

  /**
   * * 火星坐标系 (GCJ-02) to 国际坐标
   *
   * @param ggLat 纬度
   * @param ggLgt 经度
   * @return GpsTranslateDTO
   */
  public static GpsTranslateDTO gcj02ToWgs84(double ggLat, double ggLgt) {
    GpsTranslateDTO gps = transform(ggLat, ggLgt);
    double wgsLgt = ggLgt * 2 - gps.getLgt();
    double wgsLat = ggLat * 2 - gps.getLat();
    return new GpsTranslateDTO(wgsLat, wgsLgt);
  }

  /**
   * 火星坐标系 (GCJ-02) to 百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
   *
   * @param ggLat 纬度
   * @param ggLgt 经度
   * @return GpsTranslateDTO
   */
  public static GpsTranslateDTO gcj02ToBd09(double ggLat, double ggLgt) {
    double z = Math.sqrt(ggLgt * ggLgt + ggLat * ggLat) + 0.00002 * Math.sin(ggLat * X_PI);
    double theta = Math.atan2(ggLat, ggLgt) + 0.000003 * Math.cos(ggLgt * X_PI);
    double bdLgt = z * Math.cos(theta) + 0.0065;
    double bdLat = z * Math.sin(theta) + 0.006;
    return new GpsTranslateDTO(bdLat, bdLgt);
  }

  /**
   * * 百度坐标系 (BD-09) to 火星坐标系 (GCJ-02) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标
   *
   * @param bdLat 纬度
   * @param bdLgt 经度
   * @return GpsTranslateDTO
   */
  public static GpsTranslateDTO bd09ToGcj02(double bdLat, double bdLgt) {
    double x = bdLgt - 0.0065, 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 ggLgt = z * Math.cos(theta);
    double ggLat = z * Math.sin(theta);
    return new GpsTranslateDTO(ggLat, ggLgt);
  }

  /**
   * 百度坐标系 (BD-09) to 国际坐标
   *
   * @param bdLat 纬度
   * @param bdLgt 经度
   * @return GpsTranslateDTO
   */
  public static GpsTranslateDTO bd09ToWgs84(double bdLat, double bdLgt) {
    GpsTranslateDTO gcj02 = bd09ToGcj02(bdLat, bdLgt);
    return gcj02ToWgs84(gcj02.getLat(), gcj02.getLgt());
  }

  /**
   * 国际坐标 to 百度坐标系 (BD-09)
   *
   * @param wgsLat 纬度
   * @param wgsLgt 经度
   * @return GpsTranslateDTO
   */
  public static GpsTranslateDTO wgs84ToBd09(double wgsLat, double wgsLgt) {
    GpsTranslateDTO gcj02 = wgs84ToGcj02(wgsLat, wgsLgt);
    if (null == gcj02) {
      return new GpsTranslateDTO(0.0, 0.0);
    }
    return gcj02ToBd09(gcj02.getLat(), gcj02.getLgt());
  }

  /**
   * dddmmmmmm格式国际坐标 to 百度坐标系 (BD-09)
   *
   * @param wgsLat 纬度
   * @param wgsLgt 经度
   * @return
   */
  public static GpsTranslateDTO wgs84ToBd09(int wgsLat, int wgsLgt) {
    return wgs84ToBd09(changeRad(wgsLat), changeRad(wgsLgt));
  }

  private static boolean outOfChina(double lat, double lon) {
    return lon < 72.004 || lon > 137.8347 || lat < 0.8293 || lat > 55.8271;
  }

  private static GpsTranslateDTO transform(double lat, double lon) {
    if (outOfChina(lat, lon)) {
      return new GpsTranslateDTO(lat, lon);
    }
    double dLat = transformLat(lon - 105.0, lat - 35.0);
    double dLon = transformLon(lon - 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) / ((GLOBAL_R * (1 - EE)) / (magic * sqrtMagic) * PI);
    dLon = (dLon * 180.0) / (GLOBAL_R / sqrtMagic * Math.cos(radLat) * PI);
    double mgLat = lat + dLat;
    double mgLon = lon + dLon;
    return new GpsTranslateDTO(mgLat, mgLon);
  }

  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;
  }

  /**
   * 将dddmmmmmm或者ddmmmmmm转换为十进制的度
   *
   * @param val dddmmmmmm表示的经纬度
   * @return 转化后的十进制经纬度
   */
  private static double changeRad(int val) {

    if (val >= 0) {

      return Math.round((val / 1000000 + (val - (val / 1000000) * 1000000) / 600000.0) * 100000.0)
          / 100000.0;
    } else {
      val = -val;
      return -Math.round((val / 1000000 + (val - (val / 1000000) * 1000000) / 600000.0) * 100000.0)
          / 100000.0;
    }

  }

  public static double calculateAutoSpeed(GpsDataDTO gps1, GpsDataDTO gps2) {
    double distance = calculateDistance(gps1.getLng(), gps1.getLat(), gps2.getLng(), gps2.getLat(),
        EcallConst.MILE);
    return (distance / Math.abs(TimeTransform.dateStrToUnixTimeStamp(gps1.getDate())
        - TimeTransform.dateStrToUnixTimeStamp(gps2.getDate()))) * 3.6;
  }

  public static double calculateAutoSpeed(SourceGps gps1, SourceGps gps2) {
    double distance =
        calculateDistance(gps1.getX(), gps1.getY(), gps2.getX(), gps2.getY(), EcallConst.MILE);
    return (distance / Math.abs(gps1.getT() - gps2.getT())) * 3.6;
  }

  /**
   * TODO 计算地球上两点之间的距离
   *
   * @param lat1
   * @param lng1
   * @param lat2
   * @param lng2
   * @return Create at 2017年8月10日 下午1:08:39
   */
  public static double calculateDistance(double lng1, double lat1, double lng2, double lat2,
      String mileUnit) {
    double radLat1 = rad(lat1);
    double radLat2 = rad(lat2);
    // 纬度差
    double radLatSpan = radLat1 - radLat2;
    // 经度差
    double radLngSpan = rad(lng1) - rad(lng2);

    double dis = Math.pow(Math.sin(radLatSpan / 2), 2)
        + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(radLngSpan / 2), 2);

    dis = 2 * Math.asin(Math.min(1, Math.sqrt(dis))) * EcallConst.EARTH_RADIUS_CENTER;

    switch (mileUnit) {
      // 千米
      case EcallConst.KMILE:
        return MathUtil.round(dis, 3);
      // 米
      case EcallConst.MILE:
        return MathUtil.round(dis * 1000, 3);
      // 厘米
      case EcallConst.CMILE:
        return MathUtil.round(dis * 100000, 3);
      default:
        // 默认返回千米
        return MathUtil.round(dis, 3);
    }
  }

  private static double rad(double d) {
    return d * Math.PI / 180.0;
  }

  public static JSONObject gpsJsonFromPojo(double[] xy, double hight, long time) {
    JSONObject ob = new JSONObject();
    ob.put(PojoFieldConst.GPS_LONGITUDE, MathUtil.round(xy[0], 6));
    ob.put(PojoFieldConst.GPS_LATITUDE, MathUtil.round(xy[1], 6));
    ob.put(PojoFieldConst.GPS_ALTITUDE, hight);
    ob.put(PojoFieldConst.GPS_DATE, TimeTransform.unixTimeStampToDateStr(time));
    return ob;
  }

  public static JSONObject gpsJsonFromPojo(double[] xy, double hight, String date) {
    JSONObject ob = new JSONObject();
    ob.put(PojoFieldConst.GPS_LONGITUDE, MathUtil.round(xy[0], 6));
    ob.put(PojoFieldConst.GPS_LATITUDE, MathUtil.round(xy[1], 6));
    ob.put(PojoFieldConst.GPS_ALTITUDE, hight);
    ob.put(PojoFieldConst.GPS_DATE, date);
    return ob;
  }

  public static double su(double num) {
    BigDecimal bg = new BigDecimal(num);
    return bg.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
  }


  public static void main(String[] args) {
    GpsTranslateDTO wgs84ToBd09 = wgs84ToBd09(经度, 维度);
    System.out.println(su(wgs84ToBd09.getLat()));
    System.out.println(su(wgs84ToBd09.getLgt()));
  }
}
 

@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class GpsTranslateDTO implements Serializable {

    private static final long serialVersionUID = 5717495677928773775L;

    private Double lat;
    private Double lgt;

}

 

/**
 */
public class MathUtil {
    // 默认除法运算精度
    private static final int DEF_DIV_SCALE = 10;

    /**
     * 提供精确的加法运算。
     * 
     * @param v1
     *            被加数
     * @param v2
     *            加数
     * @return 两个参数的和
     */

    public static double add(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.add(b2).doubleValue();
    }

    /**
     * 提供精确的减法运算。
     * 
     * @param v1
     *            被减数
     * @param v2
     *            减数
     * @return 两个参数的差
     */

    public static double sub(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 提供精确的乘法运算。
     * 
     * @param v1
     *            被乘数
     * @param v2
     *            乘数
     * @return 两个参数的积
     */

    public static double mul(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.multiply(b2).doubleValue();
    }

    /**
     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
     * 
     * @param v1
     *            被除数
     * @param v2
     *            除数
     * @return 两个参数的商
     */

    public static double div(double v1, double v2) {
        return div(v1, v2, DEF_DIV_SCALE);
    }

    /**
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。
     * 
     * @param v1
     *            被除数
     * @param v2
     *            除数
     * @param scale
     *            表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */

    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供精确的小数位四舍五入处理。
     * 
     * @param val
     *            需要四舍五入的数字
     * @param scale
     *            小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double val, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(val);
        BigDecimal one = new BigDecimal(1.0);
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
}
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值