/**
* @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();
}
}
android 根据经纬度获取对应时区 安卓过去gps定位经纬度
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
python抓取经纬度信息
爬取城市经纬度信息
ci 结果集 返回结果