提供以下的坐标系互相转换:
GCJ-02(火星坐标系)转换为WGS84坐标系
BD-09(百度坐标系)转换为WGS84坐标系
BD-09(百度坐标系)转换为GCJ-02(火星坐标)
sogou转换为WGS84
/**
* @author jy 地图转换测试/
*/
public final class MapUtil {
/**
* 辅助类禁止共有构造函数
*/
private MapUtil() {
}
/**
* 常量:pi
*/
public static final double CONSTANT_PI = 3.1415926535897932384626;
/**
* 常量:a
*/
public static final double CONSTANT_A = 6378245.0;
/**
* 常量:e
*/
public static final double CONSTANT_E = 0.00669342162296594323;
/**
* 常量:ccc
*/
private static final double[] CCC = new double[]{12890594.86, 8362377.87, 5591021, 3481989.83, 1678043.12, 0};
/**
* 常量:ddd
*/
private static final double[][] DDD = {
new double[]{1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 200.9824383106796,
-187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653,
17337981.2},
new double[]{-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289, 96.32687599759846,
-1.85204757529826, -59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375,
10260144.86},
new double[]{-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616, 59.74293618442277,
7.357984074871, -25.38371002664745, 13.45380521110908, -3.29883767235584, 0.32710905363475,
6856817.37},
new double[]{-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591, 40.31678527705744,
0.65659298677277, -4.44255534477492, 0.85341911805263, 0.12923347998204, -0.04625736007561,
4482777.06},
new double[]{3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062, 23.10934304144901,
-0.00023663490511, -0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332,
2555164.4},
new double[]{2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 7.47137025468032,
-0.00000353937994, -0.02145144861037, -0.00001234426596, 0.00010322952773, -0.00000323890364,
826088.5}};
/**
* GCJ-02(火星坐标系)转换为WGS84坐标系<br>
* GCJ-02:谷歌中国地图、搜搜中国地图、高德地图<br>
*
* @param lat 纬度
* @param lon 经度
* @return
*/
public static Coord gcj02ToWgs84(double lat, double lon) {
Coord coord = transform(lat, lon);
double finalLon = lon * 2 - coord.getLon();
double finalLat = lat * 2 - coord.getLat();
return new Coord(finalLat, finalLon);
}
/**
* BD-09(百度坐标系)转换为WGS84坐标系<br>
*
* @param lat 纬度
* @param lon 经度
* @return
*/
public static Coord bd09ToWgs84(double lat, double lon) {
Coord gcj02 = MapUtil.bd09ToGcj02(lat, lon);
Coord wgs84 = MapUtil.gcj02ToWgs84(gcj02.getLat(), gcj02.getLon());
return wgs84;
}
/**
* BD-09(百度坐标系)转换为GCJ-02(火星坐标)<br>
*
* @param lat 纬度
* @param lon 经度
* @return
*/
public static Coord bd09ToGcj02(double lat, double lon) {
double x = lon - 0.0065;
double y = lat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * CONSTANT_PI);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * CONSTANT_PI);
double finalLon = z * Math.cos(theta);
double finalLat = z * Math.sin(theta);
return new Coord(finalLat, finalLon);
}
/**
* sogou转换为WGS84
*
* @param lat 纬度
* @param lon 经度
* @return
*/
public static Coord sogouToWgs84(double lat, double lon) {
Coord coord = new Coord(lat, lon);
Coord tmp = new Coord();
tmp.setLon(Math.abs(coord.getLon()));
tmp.setLat(Math.abs(coord.getLat()));
double[] obj = new double[9];
for (int i = 0; i < CCC.length; i++) {
if (tmp.getLat() > CCC[i]) {
obj = DDD[i];
break;
}
}
return MapUtil.convert(coord, obj);
}
/**
* sogou内部转换函数
*
* @param coord
* @param varAttr
* @return
*/
private static Coord convert(Coord coord, double[] varAttr) {
Coord tmp = new Coord();
tmp.setLon(varAttr[0] + varAttr[1] * Math.abs(coord.getLon()));
double f = Math.abs(coord.getLat()) / varAttr[9];
double tmpLat = varAttr[2] + varAttr[3] * f + varAttr[4] * f * f + varAttr[5] * f * f * f
+ varAttr[6] * f * f * f * f + varAttr[7] * f * f * f * f * f + varAttr[8] * f * f * f * f * f * f;
tmp.setLat(tmpLat);
tmp.setLon(tmp.getLon() * (coord.getLon() < 0 ? -1 : 1));
tmp.setLat(tmp.getLat() * (coord.getLat() < 0 ? -1 : 1));
return tmp;
}
/**
* 坐标点转换函数
*
* @param lat 纬度
* @param lon 经度
* @return
*/
private static Coord transform(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new Coord(lat, lon);
}
double dLat = transformLat(lat - 35.0, lon - 105.0);
double dLon = transformLon(lat - 35.0, lon - 105.0);
double radLat = lat / 180.0 * CONSTANT_PI;
double magic = Math.sin(radLat);
magic = 1 - CONSTANT_E * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((CONSTANT_A * (1 - CONSTANT_E)) / (magic * sqrtMagic) * CONSTANT_PI);
dLon = (dLon * 180.0) / (CONSTANT_A / sqrtMagic * Math.cos(radLat) * CONSTANT_PI);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new Coord(mgLat, mgLon);
}
/**
* 纬度转换函数
*
* @param lat 维度
* @param lon 经度
* @return
*/
private static double transformLat(double lat, double lon) {
double ret = -100.0 + 2.0 * lon + 3.0 * lat + 0.2 * lat * lat + 0.1 * lon * lat
+ 0.2 * Math.sqrt(Math.abs(lon));
ret += (20.0 * Math.sin(6.0 * lon * CONSTANT_PI) + 20.0 * Math.sin(2.0 * lon * CONSTANT_PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lat * CONSTANT_PI) + 40.0 * Math.sin(lat / 3.0 * CONSTANT_PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(lat / 12.0 * CONSTANT_PI) + 320 * Math.sin(lat * CONSTANT_PI / 30.0)) * 2.0 / 3.0;
return ret;
}
/**
* 经度转换函数
*
* @param lat 纬度
* @param lon 经度
* @return
*/
private static double transformLon(double lat, double lon) {
double ret = 300.0 + lon + 2.0 * lat + 0.1 * lon * lon + 0.1 * lon * lat + 0.1 * Math.sqrt(Math.abs(lon));
ret += (20.0 * Math.sin(6.0 * lon * CONSTANT_PI) + 20.0 * Math.sin(2.0 * lon * CONSTANT_PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lon * CONSTANT_PI) + 40.0 * Math.sin(lon / 3.0 * CONSTANT_PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(lon / 12.0 * CONSTANT_PI) + 300.0 * Math.sin(lon / 30.0 * CONSTANT_PI)) * 2.0 / 3.0;
return ret;
}
/**
* 判断坐标点是否在中国范围内
*
* @param lat
* @param lon
* @return
*/
private 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;
}
}
public class Coord implements Serializable {
/**
*
*/
private static final long serialVersionUID = -229841606158709053L;
/**
* 纬度
*/
private double lat;
/**
* 经度
*/
private double lon;
/**
* 默认构造参数
*/
public Coord() {
}
/**
* 重载构造方法
*
* @param lat 纬度
* @param lon 经度
*/
public Coord(double lat, double lon) {
this.lat = lat;
this.lon = lon;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
}