火星坐标系 (GCJ 02) 与百度坐标系 (BD 09) 的互转 以及其他经纬度相关方法 - s9797456/MyCommonCodeSnippets GitHub Wiki

package com.xinle.car.admin.common.util;

import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.util.Arrays; import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject;

/**

  • 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的互转 以及其他经纬度相关方法

  • http://blog.csdn.net/a13570320979/article/details/51366355 */ public class GPSUtil { public static final double pi = 3.1415926535897932384626;
    public static final double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
    public static final double a = 6378245.0;
    public static final double ee = 0.00669342162296594323; public static final double DICTINCE_COV = 0.01745329251994329D;

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

    public 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;
    }
    public static Double[] transform(double lat, double lon) {
    if (outOfChina(lat, lon)) {
    return new Double[]{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) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
    dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
    double mgLat = lat + dLat;
    double mgLon = lon + dLon;
    return new Double[]{mgLat,mgLon};
    }

    /**

    • 坐标点经纬度是否在国外(国外坐标点经纬度不需要转换)
    • @param lat
    • @param lon
    • @return */ public static boolean outOfChina(double lat, double lon) {
      if (lon < 72.004 || lon > 137.8347)
      return true;
      if (lat < 0.8293 || lat > 55.8271)
      return true;
      return false;
      }

    /**

    • 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System
    • @param lat
    • @param lon
    • @return */
      public static Double[] gps84_To_Gcj02(double lat, double lon) {
      if (outOfChina(lat, lon)) {
      return new Double[]{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) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
      dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
      double mgLat = lat + dLat;
      double mgLon = lon + dLon;
      return new Double[]{mgLon, mgLat};
      }

    /**

    • 火星坐标系 (GCJ-02) to 84
    • @param lon
    • @param lat
    • @return

    */
    public static double[] gcj02_To_Gps84(double lat, double lon) {
    Double[] gps = transform(lat, lon);
    double lontitude = lon * 2 - gps[1];
    double latitude = lat * 2 - gps[0];
    return new double[]{latitude, lontitude};
    }

    /**

    • 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
    • @param lat
    • @param lon */
      public static Double[] gcj02_To_Bd09(double lat, double lon) {
      double x = lon, y = lat;
      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 tempLon = z * Math.cos(theta) + 0.0065;
      double tempLat = z * Math.sin(theta) + 0.006;
      Double[] gps = {tempLat,tempLon};
      return gps;
      }

    /**

    • 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param
    • bd_lat * @param bd_lon * @return */
      public static double[] bd09_To_Gcj02(double lat, double lon) {
      double x = lon - 0.0065, y = lat - 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 tempLon = z * Math.cos(theta);
      double tempLat = z * Math.sin(theta);
      double[] gps = {tempLat,tempLon};
      return gps;
      }

    /**

    • 将gps84转为bd09
    • @param lat
    • @param lon
    • @return */
      public static Double[] gps84_To_bd09(double lat, double lon){
      Double[] gcj02 = gps84_To_Gcj02(lat,lon);
      Double[] bd09 = gcj02_To_Bd09(gcj02[0],gcj02[1]);
      return bd09;
      }

    /**

    • 将bd09转为 gps84
    • @param lat
    • @param lon
    • @return */ public static double[] bd09_To_gps84(double lat, double lon){
      double[] gcj02 = bd09_To_Gcj02(lat, lon);
      double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]);
      //保留小数点后六位
      gps84[0] = retain6(gps84[0]);
      gps84[1] = retain6(gps84[1]);
      return gps84;
      }

    /**

    • 计算两个经纬度之间的距离
    • lat 小 log 大 */ public static double GetDistance(double lng1, double lat1, double lng2, double lat2) { double var4 = lng1 * DICTINCE_COV; double var6 = lat1 * DICTINCE_COV; double var8 = lng2 * DICTINCE_COV; double var10 = lat2 * DICTINCE_COV; double var12 = Math.sin(var4); double var14 = Math.sin(var6); double var16 = Math.cos(var4); double var18 = Math.cos(var6); double var20 = Math.sin(var8); double var22 = Math.sin(var10); double var24 = Math.cos(var8); double var26 = Math.cos(var10); double[] var28 = new double[3]; double[] var29 = new double[3]; var28[0] = var18 * var16; var28[1] = var18 * var12; var28[2] = var14; var29[0] = var26 * var24; var29[1] = var26 * var20; var29[2] = var22; double var30 = Math.sqrt((var28[0] - var29[0]) * (var28[0] - var29[0]) + (var28[1] - var29[1]) * (var28[1] - var29[1]) + (var28[2] - var29[2]) * (var28[2] - var29[2])); return (float)(Math.asin(var30 / 2.0D) * 1.27420015798544E7D); }

    /**

    • 根据经纬度获取地名
    • lat 小 log 大 */ public static String getAdd(String log, String lat) { // lat 小 log 大 // 参数解释: 纬度,经度 type 001 (100代表道路,010代表POI,001代表门址,111可以同时显示前三项) String urlString = "http://gc.ditu.aliyun.com/regeocoding?l=" + lat + "," + log + "&type=010"; StringBuffer res = new StringBuffer(); try { URL url = new URL(urlString); java.net.HttpURLConnection conn = (java.net.HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setRequestMethod("POST"); BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); String line; while ((line = in.readLine()) != null) { res.append(line); } in.close(); } catch (Exception e) { System.out.println("error in wapaction,and e is " + e.getMessage()); } return res.toString(); }

    @SuppressWarnings("rawtypes") public static String getAddName(String lng, String lat) { String addName = ""; String add = ""; try { add = getAdd(lng, lat);

     	Map map = (Map) JSON.parse(add); // 先转换成Object
     	JSONArray nameMap = (JSONArray) map.get("addrList");
     	JSONObject j_2 = nameMap.getJSONObject(0); 
     	String allAdd = j_2.getString("admName");
     	String arr[] = allAdd.split(",");
     	if(arr.length == 3) {
     		addName = arr[2] + j_2.getString("addr") + j_2.getString("name");
     	}else {
     		addName = j_2.getString("addr") + j_2.getString("name");
     	}
     }catch(Exception e) {
     }
     if(StringUtils.isBlank(addName)) {
     	addName = "地址名称转换失败";
     }
     return addName;
    

    }

    /**

    • 保留小数点后六位
    • @param num
    • @return */
      private static double retain6(double num){
      String result = String .format("%.6f", num);
      return Double.valueOf(result);
      }

    public static void main(String[] args) { // [114.04291, 22.527493] [113.87546, 22.568424] [114.04066, 22.715206] [114.11545, 22.545536] // [113.96032, 22.566998] [114.11932, 22.54414] [114.06837, 22.531603] [113.674095, 22.869143] double lat1 = 114.04291, lon1 = 22.527493; Double[] real = gps84_To_Gcj02(lon1, lat1); System.out.println("==============>"); System.out.println(Arrays.toString(real)); // 22.5247138900,114.0479726400

     double lat2 = 113.87546, lon2 = 22.568424;
     Double[] real2 = gps84_To_Gcj02(lon2, lat2);
     System.out.println("==============>");
     System.out.println(Arrays.toString(real2)); // 22.5653925300,113.8803630500
     
     double lat3 = 114.04066, lon3 = 22.715206;
     Double[] real3 = gps84_To_Gcj02(lon3, lat3);
     System.out.println("==============>");
     System.out.println(Arrays.toString(real3)); // 22.7124798600,114.0457578400
     
     double lat4 = 114.11545, lon4 = 22.545536;
     Double[] real4 = gps84_To_Gcj02(lon4, lat4);
     System.out.println("==============>");
     System.out.println(Arrays.toString(real4)); // 22.5428395000,114.1205429800
     
     String addName = getAddName("114.041084", "22.616901");
     System.out.println(addName);
     
     //获取两点之间距离
     //海事局--中医院
     double dist = GetDistance(114.092406,22.534082, 114.085346,22.537016);
     System.out.println(dist);
    

    } }