开发时我们有两个项目,一个web端,都涉及到地图,所以坐标系的统一至关重要,问题是,我们两个项目一个高德,一个百度,web端用的是天地图,在上传坐标的时候都涉及到了坐标转换的问题,那么我们常用的地图都是什么坐标系呢
参考博客:http://blog.csdn.net/jiang117/article/details/48031927
上面介绍的很清楚,我这里就简单的说,方便运用。
android 开发一般都使用高德地图或者百度地图,常见的坐标系就是gs和84,gc也就是火星坐标系,
84就是大地坐标系,LocationManager获取的就是这个坐标系
gc(国测局)就是我国使用的,又名”火星坐标系“当然也就是加密的坐标系,高德地图、搜狗地图等,就是使用了这一套坐标系
百度地图则是在gc的基础上自己加密的一个坐标系
所以在转换的时候就设计到了gc、84、百度之间的转换。
这个基本也就全了,方便大家使用
public class GCJ02ToWGS84Util { /** * 地球坐标系 (WGS-84) 相互转火星坐标系 (GCJ-02) 的转换算法 * * @author jxh * @time 2013-5-16 */ private static double pi = 3.14159265358979324D;// 圆周率 private static double a = 6378245.0D;// WGS 长轴半径 private static double ee = 0.00669342162296594323D;// WGS 偏心率的平方 private static double x_pi = 3.14159265358979324 * 3000.0 / 180.0; /** * 中国坐标内 * * @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; } 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; } // 84->gcj02 public static Map<String, Double> transform(double lon, double lat) { HashMap<String, Double> localHashMap = new HashMap<String, Double>(); if (outofChina(lat, lon)) { localHashMap.put("lon", Double.valueOf(lon)); localHashMap.put("lat", Double.valueOf(lat)); return localHashMap; } 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; localHashMap.put("lon", mgLon); localHashMap.put("lat", mgLat); return localHashMap; } // gcj02-84 public static Map<String, Double> gcj2wgs(double lon, double lat) { Map<String, Double> localHashMap = new HashMap<String, Double>(); double lontitude = lon - (((Double) transform(lon, lat).get("lon")).doubleValue() - lon); double latitude = (lat - (((Double) (transform(lon, lat)).get("lat")) .doubleValue() - lat)); localHashMap.put("lon", lontitude); localHashMap.put("lat", latitude); return localHashMap; } /** * 火星坐标转换为百度坐标 * * @param gg_lat * @param gg_lon */ public static Map<String, Double> bd_encrypt(double gg_lat, double gg_lon) { Map<String, Double> bdlocalHashMap = new HashMap<String, Double>(); double x = gg_lon, y = gg_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 bd_lon = z * Math.cos(theta) + 0.0065; double bd_lat = z * Math.sin(theta) + 0.006; bdlocalHashMap.put("lon", bd_lon); bdlocalHashMap.put("lat", bd_lat); return bdlocalHashMap; } /** * 84转百度 * * @param latitude 纬度 * @param longitude 经度 * @return */ public static Map<String, Double> wgs84_bd09(double latitude, double longitude) { //1,将84转国测局gcj-02 Map<String, Double> mapForGCJ = transform(longitude, latitude); Double lonGCJ = mapForGCJ.get("lon"); Double latGCJ = mapForGCJ.get("lat"); //2.将gcj-02转百度 Map<String, Double> mapForBD09 = bd_encrypt(latGCJ, lonGCJ); return mapForBD09; } /** * 百度转gcj02 */ public static Map<String, Double> bd09togcj02(double bd_lon, double bd_lat){ Map<String, Double> bdtogcmap = new HashMap<>(); double x = bd_lon - 0.0065; double y = bd_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 gg_lng = z * Math.cos(theta); double gg_lat = z * Math.sin(theta); bdtogcmap.put("lon", gg_lng); bdtogcmap.put("lat", gg_lat); return bdtogcmap; } /** * 百度转84 */ public static Map<String, Double> bd09to84(double bd_lon, double bd_lat){ Map<String, Double> bdtogcmap = bd09togcj02(bd_lon, bd_lat); Double lon = bdtogcmap.get("lon"); Double lat = bdtogcmap.get("lat"); Map<String, Double> gcto84map = gcj2wgs(lon, lat); return gcto84map; } }
添加84和墨卡托的转换(借鉴:http://www.gisall.com/html/68/104468-4865.html)
[cpp] view plaincopy
- //经纬度转Wev墨卡托
- dvec3 CMathEngine::lonLat2WebMercator(dvec3 lonLat)
- {
- dvec3 mercator;
- double x = lonLat.x *20037508.34/180;
- double y = log(tan((90+lonLat.y)*PI/360))/(PI/180);
- y = y *20037508.34/180;
- mercator.x = x;
- mercator.y = y;
- return mercator ;
- }
- //Web墨卡托转经纬度
- dvec3 CMathEngine::WebMercator2lonLat( dvec3 mercator )
- {
- dvec3 lonLat;
- double x = mercator.x/20037508.34*180;
- double y = mercator.y/20037508.34*180;
- y= 180/PI*(2*atan(exp(y*PI/180))-PI/2);
- lonLat.x = x;
- lonLat.y = y;
- return lonLat;
- }
经过笔者测试,与Google map dowloader软件系列的转换器相比,在14级别的某地图上测试有0.04个像素误差,基本可以无视。
其他级别和经纬区域有待测试。