import java.io.Serializable;
public class GpsPoint implements Serializable {
/**
* 序列化.
*/
private static final long serialVersionUID = 1L;
/**
* 纬度.
*/
private double lat;
/**
* 经度.
*/
private double lon;
/**
* 构造函数.
* @param lat 纬度
* @param lon 经度
*/
public GpsPoint(double lat, double lon) {
setLat(lat);
setLon(lon);
}
/**
* 设置lat.
* @return 返回lat
*/
public double getLat() {
return lat;
}
/**
* 设置lon.
* @return 返回lon
*/
public double getLon() {
return lon;
}
/**
* 获取lat.
* @param lat 要设置的lat
*/
public void setLat(double lat) {
this.lat = lat;
}
/**
* 获取lon.
* @param lon 要设置的lon
*/
public void setLon(double lon) {
this.lon = lon;
}
@Override
public String toString() {
return lat + "," + lon;
}
}
import java.math.BigDecimal;
public class GpsPointUtils {
/**
* pi圆周率.
*/
public static double pi = 3.1415926535897932384626;
/**
* 百度地图混淆系数.
*/
public static double xpi = 3.1415926535897932384626 * 3000.0 / 180.0;
/**
* 地球半径.
*/
public static double a = 6378245.0;
/**
* 混淆系数.
*/
public static double ee = 0.00669342162296594323;
/**
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标.
* @param bdlat 百度纬度
* @param bdlon 百度经度
* @return gps点
*/
public static GpsPoint bd09Togcj02(double bdlat, double bdlon) {
double x = bdlon - 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 gglon = z * Math.cos(theta);
double gglat = z * Math.sin(theta);
BigDecimal b = new BigDecimal(gglon);
double f1 = b.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
BigDecimal b1 = new BigDecimal(gglat);
double f2 = b1.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
return new GpsPoint(f2, f1);
}
/**
* (BD-09)-->84.
* @param bdlat 纬度
* @param bdlon 经度
* @return Gps点
*/
public static GpsPoint bd09Towgs84(double bdlat, double bdlon) {
GpsPoint gcj02 = GpsPointUtils.bd09Togcj02(bdlat, bdlon);
GpsPoint map84 = GpsPointUtils.gcj02Towgs84(gcj02.getLat(), gcj02.getLon());
return map84;
}
/**
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标.
* @param gglat gcj纬度
* @param gglon gcj经度
* @return gps点
*/
public static GpsPoint gcj02Tobd09(double gglat, double gglon) {
double x = gglon;
double y = gglat;
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 bdlon = z * Math.cos(theta) + 0.0065;
double bdlat = z * Math.sin(theta) + 0.006;
BigDecimal b = new BigDecimal(bdlon);
double f1 = b.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
BigDecimal b1 = new BigDecimal(bdlat);
double f2 = b1.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
return new GpsPoint(f2, f1);
}
/**
* 火星坐标系 (GCJ-02) to 84.
* @param lon gcj纬度
* @param lat gcj经度
* @return gps点
*/
public static GpsPoint gcj02Towgs84(double lat, double lon) {
GpsPoint gps = gcj02Towgs84inner(lat, lon);
double lat84 = gps.getLat();
double lon84 = gps.getLon();
int i = 20;
while (i > 0) {
i--;
lat84 = gps.getLat();
lon84 = gps.getLon();
GpsPoint gcj02 = wgs84Togcj02(gps.getLat(), gps.getLon());
if (i == 0) {
break;
}
double midlat = gcj02.getLat() - lat;
double midlon = gcj02.getLon() - lon;
gps = gcj02Towgs84inner(lat - midlat, lon - midlon);
}
return new GpsPoint(lat84, lon84);
}
/**
* 内部测试.
* @param args .
*/
public static void main(String[] args) {
// 北斗芯片获取的经纬度为WGS84地理坐标 31.426896,119.496145
GpsPoint gps = new GpsPoint(31.424929141368278, 119.50130435845807);
System.out.println("gps :" + gps);
GpsPoint gcj = wgs84Togcj02(gps.getLat(), gps.getLon());
System.out.println("gcj :" + gcj);
GpsPoint star = gcj02Towgs84(gcj.getLat(), gcj.getLon());
System.out.println("gps :" + star);
GpsPoint bd = gcj02Tobd09(gcj.getLat(), gcj.getLon());
System.out.println("bd :" + bd);
GpsPoint gcj2 = bd09Togcj02(bd.getLat(), bd.getLon());
System.out.println("gcj :" + gcj2);
GpsPoint gps2 = gcj02Towgs84(gcj2.getLat(), gcj2.getLon());
System.out.println("gps :" + gps2);
}
/**
* 判断经纬度是否在国外.
* @param lat 纬度
* @param lon 经度
* @return true-在国外,false-在国内
*/
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 bd09.
* @param lat 纬度
* @param lon 经度
* @return Gps点
*/
public static GpsPoint wgs84Todb09(double lat, double lon) {
GpsPoint gps = wgs84Togcj02(lat, lon);
gps = gcj02Tobd09(gps.getLat(), gps.getLon());
return gps;
}
/**
* 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System.
* @param lat 纬度
* @param lon 经度
* @return Gps点
*/
public static GpsPoint wgs84Togcj02(double lat, double lon) {
if (outOfChina(lat, lon)) {
return null;
}
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 GpsPoint(mgLat, mgLon);
}
/**
* 火星坐标系 (GCJ-02) to 84.
* @param lat 纬度
* @param lon 经度
* @return gps点
*/
private static GpsPoint gcj02Towgs84inner(double lat, double lon) {
GpsPoint gps = transform(lat, lon);
double lontitude = lon * 2 - gps.getLon();
double latitude = lat * 2 - gps.getLat();
return new GpsPoint(latitude, lontitude);
}
/**
* 内部纠偏函数.
* @param lat 纬度
* @param lon 经度
* @return .
*/
private static GpsPoint transform(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new GpsPoint(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 GpsPoint(mgLat, mgLon);
}
/**
* 转换纬度.
* @param x x
* @param y y
* @return double
*/
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;
}
/**
* 转换经度.
* @param x x
* @param y y
* @return 纬度
*/
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;
}
}