座標系定義和相互轉換演算法
座標系定義
- 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座標系(線上高德地圖和線上百度地圖) 就可以使用上面的網址查詢。
相關文章
- GIS中的座標系定義與轉換 (轉)
- ogre世界座標魚螢幕座標相互轉換
- ArcEngine下投影座標和經緯度座標的相互轉換
- Qt - 座標系及轉換QT
- 地心地固座標系(ECEF)與站心座標系(ENU)的轉換
- 火星座標和正常座標之間的轉換
- ROS TF :使用 TF 設定機器人 釋出座標變換 使用座標變換 將感測器資料轉換為機器人座標系下ROS機器人
- 利用齊次座標進行二維座標轉換
- iOS地球座標、火星座標和百度座標之間轉換(Swift3.0)iOSSwift
- Python pytorch 座標系變換與維度轉換PythonPyTorch
- RVA和RAW相互轉換
- MathNet Ray3D座標系下轉換3D
- ArcGIS地圖投影與座標系轉換的方法地圖
- Go版本的各座標系互相轉換的工具Go
- OpenGL ES on iOS --- 座標系統與矩陣轉換iOS矩陣
- GPS座標轉換為BIM
- gcoord: 轉換WGS84、GCJ02、BD09座標,轉換百度高德地圖座標系GC地圖
- 張正友標定Opencv實現、標定流程以及影像座標轉為世界座標OpenCV
- android自定義View——座標系AndroidView
- 理解SVG座標系統和變換: transform屬性SVGORM
- 三維空間座標系變換-旋轉矩陣矩陣
- 形象化理解笛卡爾座標系和極座標系
- 理解SVG座標系和變換:視窗,viewBox和preserveAspectRatioSVGView
- 各種座標系互相轉換(WGS84轉換BD-09主要)
- 百度座標轉換API使用API
- 機器人工具座標系標定原理機器人
- 理解SVG座標系統和變換: 建立新視窗SVG
- 安卓自定義View基礎:座標系安卓View
- C++ opencv的圓轉矩形,極座標轉笛卡爾座標系C++OpenCV
- OpenGL座標系與幾何變換
- 海康相機 畫素座標(px,py)到sdk ptz 座標轉換最後到onvif ptz座標
- pose座標變換
- 陣列和集合的相互轉換陣列
- javascript數字和字串相互轉換JavaScript字串
- 字串和陣列的相互轉換字串陣列
- JavaScript全形和半形相互轉換JavaScript
- 字串和數字的相互轉換字串
- iOS開發中常見定位座標轉換iOS