首页 / 算法 / 坐标系定义和相互转换算法
坐标系定义和相互转换算法
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了坐标系定义和相互转换算法,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含10205字,纯文字阅读大概需要15分钟。
内容图文
![坐标系定义和相互转换算法](/upload/InfoBanner/zyjiaocheng/618/c216ba1526594e15ab498815c37431db.jpg)
坐标系定义
- WGS84坐标系:即地球坐标系,国际上通用的坐标系。Earth
- GCJ02坐标系:即火星坐标系,WGS84坐标系经加密后的坐标系。Mars
- BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系。 Bd09
常见的api 返回的坐标系
- 百度地图api返回的是百度坐标(BD09)
- 高德,阿里云地图api 返回的都是火星坐标(常用)
- 腾讯搜搜地图API 火星坐标
- 灵图51ditu地图API 火星坐标(不常用)
坐标系转换算法
-
基本参数
private static double PI = Math.PI; // 圆周率 private static double AXIS = 6378245.0; //轴 private static double OFFSET = 0.00669342162296594323; //偏移量 (a^2 - b^2) private static double X_PI = PI * 3000.0 / 180.0;
-
GCJ-02=>BD09 火星坐标系=>百度坐标系
public static double[] gcj2BD09(double glat, double glon) { double x = glon; double y = glat; double[] latlon = new double[2]; 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); latlon[0] = z * Math.sin(theta) + 0.006; latlon[1] = z * Math.cos(theta) + 0.0065; return latlon; }
-
BD09=>GCJ-02 百度坐标系=>火星坐标系
public static double[] bd092GCJ(double glat, double glon) { double x = glon - 0.0065; double y = glat - 0.006; double[] latlon = new double[2]; 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); latlon[0] = z * Math.sin(theta); latlon[1] = z * Math.cos(theta); return latlon; }
-
BD09=>WGS84 百度坐标系=>地球坐标系
public static double[] bd092WGS(double glat, double glon) { double[] latlon = bd092GCJ(glat, glon); return gcj2WGS(latlon[0], latlon[1]); }
-
WGS84=>BD09 地球坐标系=>百度坐标系
public static double[] wgs2BD09(double wgLat, double wgLon) { double[] latlon = wgs2GCJ(wgLat, wgLon); return gcj2BD09(latlon[0], latlon[1]); }
-
WGS84=>GCJ02 地球坐标系=>火星坐标系
public static double[] wgs2GCJ(double wgLat, double wgLon) { double[] latlon = new double[2]; if (outOfChina(wgLat, wgLon)) { latlon[0] = wgLat; latlon[1] = wgLon; return latlon; } double[] deltaD = delta(wgLat, wgLon); latlon[0] = wgLat + deltaD[0]; latlon[1] = wgLon + deltaD[1]; return latlon; }
-
GCJ02=>WGS84 火星坐标系=>地球坐标系(粗略)
public static double[] gcj2WGS(double glat, double glon) { double[] latlon = new double[2]; if (outOfChina(glat, glon)) { latlon[0] = glat; latlon[1] = glon; return latlon; } double[] deltaD = delta(glat, glon); latlon[0] = glat - deltaD[0]; latlon[1] = glon - deltaD[1]; return latlon; }
-
GCJ02=>WGS84 火星坐标系=>地球坐标系(精确)
public static double[] gcj2WGSExactly(double gcjLat, double gcjLon) { double initDelta = 0.01; double threshold = 0.000000001; double dLat = initDelta, dLon = initDelta; double mLat = gcjLat - dLat, mLon = gcjLon - dLon; double pLat = gcjLat + dLat, pLon = gcjLon + dLon; double wgsLat, wgsLon, i = 0; while (true) { wgsLat = (mLat + pLat) / 2; wgsLon = (mLon + pLon) / 2; double[] tmp = wgs2GCJ(wgsLat, wgsLon); dLat = tmp[0] - gcjLat; dLon = tmp[1] - gcjLon; if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold)) break; if (dLat > 0) pLat = wgsLat; else mLat = wgsLat; if (dLon > 0) pLon = wgsLon; else mLon = wgsLon; if (++i > 10000) break; } double[] latlon = new double[2]; latlon[0] = wgsLat; latlon[1] = wgsLon; return latlon; }
-
两点之间距离
public static double distance(double latA, double logA, double latB, double logB) { int earthR = 6371000; double x = Math.cos(latA * Math.PI / 180) * Math.cos(latB * Math.PI / 180) * Math.cos((logA - logB) * Math.PI / 180); double y = Math.sin(latA * Math.PI / 180) * Math.sin(latB * Math.PI / 180); double s = x + y; if (s > 1) s = 1; if (s < -1) s = -1; double alpha = Math.acos(s); double distance = alpha * earthR; return distance; } public static double[] delta(double wgLat, double wgLon) { double[] latlng = new double[2]; double dLat = transformLat(wgLon - 105.0, wgLat - 35.0); double dLon = transformLon(wgLon - 105.0, wgLat - 35.0); double radLat = wgLat / 180.0 * PI; double magic = Math.sin(radLat); magic = 1 - OFFSET * magic * magic; double sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((AXIS * (1 - OFFSET)) / (magic * sqrtMagic) * PI); dLon = (dLon * 180.0) / (AXIS / sqrtMagic * Math.cos(radLat) * PI); latlng[0] = dLat; latlng[1] = dLon; return latlng; } 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; }
坐标加密算法
通常情况下,我们通过高德定位拿到的坐标不能直接使用,需要做一定的转换之后才能与地图服务坐标(argic)匹配,才能使用一些地图服务的操作,否则坐标对不上,地图服务引擎获取到的数据都不对的。一般我们使用以下四种(标准转标准、四参数、七参数、高斯正算)的其中一种。
-
高德定位方法回调后,我们拿到对应的坐标进行加密处理
public void onLocationChanged(AMapLocation aMapLocation){ if (aMapLocation == null) return; GpsWgs gpsWgs = getLocation(aMapLocation); }
-
标准转标准
主要参数: //目标坐标系() private int targetSpatialReference = 2437; //使用方式 (4326是WGS84 参考坐标系) point = (Point) GeometryEngine.project(new Point(Lon, Lat) , SpatialReference.create(4326) , SpatialReference.create(targetSpatialReference));
-
四参数
//主要的参数 //坐标系 private SpatialReference spatialReference; //四参数 private double k; private double red; private double dx; private double dy; //x偏移量 private double offsetX; //y偏移量 private double offsetY; //方法调用 public Point FourParamConfigLocation(GpsWgs gpsWgs){ Point mapPoint; // double[] xy1 = GaosiTool.GaussPositive_Du(gpsWgs.getWgLat(),gpsWgs.getWgLon(), mFourParamConfig.getCentralMeridian()); double dx = mFourParamConfig.getDx(); double dy = mFourParamConfig.getDy(); double red = mFourParamConfig.getRed(); double k = mFourParamConfig.getK(); double x_put = xy1[0]; double y_put = xy1[1]; double x_out = x_put * k * Math.cos(red / 180 * Math.PI) - y_put * k * Math.sin(red / 180 * Math.PI) + dx; double y_out = x_put * k * Math.sin(red / 180 * Math.PI) + y_put * k * Math.cos(red / 180 * Math.PI) + dy; mapPoint=new Point(x_out,y_out); mapPoint=movePoints(mapPoint);//如果发现位子不准,可以微调坐标进行校准 Log.e("point","X坐标:" + x_out + "\n" + "Y坐标:" + y_out); mapPoint = this.transfer(xy1[0], xy1[1], this.mFourParamConfig.getK(), this.mFourParamConfig.getRed(), this.mFourParamConfig.getDx(), this.mFourParamConfig.getDy()); return mapPoint; }
-
七参数
// 七参数主要参数 protected double XT = 0.0; protected double YT = 0.0; protected double ZT = 0.0; protected double XR = 0.0; protected double YR = 0.0; protected double ZR = 0.0; protected double K = 0.0; // 长轴,短轴,扁率 protected double _a = 0.0; protected double _b = 0.0; protected double _f = 0.0; protected double _e = 0.0; // 带宽 protected double _beltWidth = 0.0; //主要实现方法coordChangeTool public double[] coordChangeTool(double L, double B, double H) { //初始化数组 double[] xy = new double[2]; //获取84经纬度和高度 this.B_put = B; this.L_put = L; this.H_put = H; //用七参数配置进行赋值 this.middleline = _iConversion.MERIDIAN; this.zonewide = (int) _iConversion._beltWidth; this.Px = _iConversion.XT; this.Py = _iConversion.YT; this.Pz = _iConversion.ZT; this.Rx = _iConversion.XR; this.Ry = _iConversion.YR; this.Rz = _iConversion.ZR; this.K = _iConversion.K; _a = _iConversion._a; _b = _iConversion._b; _f = (1 /_iConversion._e); double _e = 1 / _f; //计算参数 //计算椭球第一偏心率 e_84 = 2 * f_84 - f_84 * f_84; //(a*a-b*b)/(a*a) //计算参考椭球的第一偏心率-e e1_54 = 2 * _f - _f * _f; //计算参考椭球的第二偏心率-e' e2_54 = Math.pow(Math.sqrt(Math.pow(_a, 2) - Math.pow(_b, 2)) / _b, 2); // 计算第一偏心率的平方 ee = (2 * _e - 1) / _e / _e; // 计算第二偏心率的平方 ee2 = ee / (1 - ee); //84转54 BLH_84To_XYZ_84(B_put, L_put, H_put); XYZ_84To_XYZ_54(X_84, Y_84, Z_84); XYZ_54_BLH_54(X_54, Y_54, Z_54); //54转80 //设置高斯椭球参数为西安80椭球参数 // SevenGaosiTool.xian_80(); SevenGaosiTool.getReset(_a,ee,0); //按制定中央经线进行高斯投影 SevenGaosiTool.GaussPositive_Du(B_54,L_54,middleline); //最终结果坐标 xy[0] = SevenGaosiTool.getYy(); xy[1] = SevenGaosiTool.getXx(); return xy; }
-
高斯正算
高斯正算主要参数 //中央经线 private double centralMeridian = 120; //椭球参数(高斯正算使用) static double LongHalfShaft = 6378137; static double firstEccentricitySquared = 0.006694380022900787; //使用方式 GaosiTool.setA(LongHalfShaft); GaosiTool.setE2(firstEccentricitySquared); double[] xy1 = GaosiTool.GaussPositive_Du(Lat, Lon, centralMeridian); point = new Point(xy1[1], xy1[0]); // 主要核心算法 public static double[] GaussPositive_Du(double B, double L, double L0) { double[] xy = new double[2]; reset(); double X, t, N, h2, l, m; double Bdu, Ldu; Bdu =B; Ldu =L; B = Bdu * PI / 180.0; L = Ldu * PI / 180.0; l = L - L0 * PI / 180; X = a0 * B - Math.sin(B) * Math.cos(B) * ((a2 - a4 + a6) + (2 * a4 - 16.0 / 3.0 * a6) * Math.sin(B) * Math.sin(B) + 16.0 / 3.0 * a6 * Math.pow(Math.sin(B), 4)) + a8 / 8.0 * Math.sin(8 * B); t = Math.tan(B); h2 = e2 / (1 - e2) * Math.cos(B) * Math.cos(B); N = a / Math.sqrt(1 - e2 * Math.sin(B) * Math.sin(B)); m = Math.cos(B) * l; xx = X + N * t * ((0.5 + (1.0 / 24.0 * (5 - t * t + 9 * h2 + 4 * h2 * h2) + 1.0 / 720.0 * (61 - 58 * t * t + Math.pow(t, 4)) * m * m) * m * m) * m * m); yy = N * ((1 + (1.0 / 6.0 * (1 - t * t + h2) + 1.0 / 120.0 * (5 - 18 * t * t + Math.pow(t, 4) + 14 * h2 - 58 * h2 * t * t) * m * m) * m * m) * m); yy = yy + 500000; xy[0]=xx; xy[1]=yy; return xy; }
参考坐标系WKID查询
当你需要用到一个标准坐标系,但是不知道他的编号时从这里找,常用的:4326是84,4490是国家2000,4549是平面的国家2000中央经线120度的,2437是北京54中央经线120度的,2385是西安80中央经线120度的,3857是墨卡托投影的84坐标系(在线高德地图和在线百度地图) 就可以使用上面的网址查询。
内容总结
以上是互联网集市为您收集整理的坐标系定义和相互转换算法全部内容,希望文章能够帮你解决坐标系定义和相互转换算法所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。