參考:
地球坐標系 (WGS-84) 到火星坐標系 (GCJ-02)百度坐標系 (BD-09) 的轉換算法
火星坐標系 (GCJ-02) 與百度坐標系 (BD-09) 的轉換算法
1. 中國國測局地理坐標(GCJ-02)<即火星坐標>
谷歌中國地圖、搜搜中國地圖、高德地圖采用的是GCJ02(其中蘋果地圖在大陸的數據源是高德)地理坐標系
2. 世界標准地理坐標(WGS-84)
谷歌地圖采用的是WGS84地理坐標系(中國范圍除外)。
3. 百度地理坐標(BD-09)
百度定位SDK可以返回三種坐標系,分別是bd09, bd09ll(默認)和gcj02,其中bd09ll能無偏差地顯示在百度地圖上。
而設備一般包含GPS芯片或者北斗芯片獲取的經緯度為WGS84地理坐標系,所以我們要根據得到的經緯度的坐標類型和地圖廠商類型在地圖上標點,否則會出現獲取的位置誤差。
注意:
后綴ll=經緯度球面坐標,mc=墨卡托平面坐標。當定位SDK中輸入gcj02時,默認為經緯度坐標,輸入bd09時,默認為墨卡托平面坐標。
百度地圖api中采用兩種坐標體系,經緯度坐標系和墨卡托投影坐標系。前者單位是度,后者單位是米,具體定義可以參見百科詞條解釋: http://baike.baidu.com/view/61394.htm和http://baike.baidu.com/view/301981.htm 。
以百度地圖為例
百度地圖采用的是自己的BD09坐標。如果我們通過GPS獲取的坐標,也就是WGS84坐標,那么我們首先要將WGS坐標轉換成BD09坐標。
轉換成百度坐標下的經緯度即可有在地圖上標點,當然,百度獲取的文字詳情不如高德,有時想要獲取位置詳情,需要調用高德的接口,而高德采用的標准是 GCJ02,因此,如果拿到百度地圖的經緯度或是GPS經緯度,則要轉成國測局的標准,以獲取位置詳細信息。
相互間的單位轉換如下:
(1)世界標准地理坐標(WGS-84) 轉換成 中國國測局地理坐標(GCJ-02)<火星坐標>
1 static double jzA = 6378245.0; 2 static double jzEE = 0.00669342162296594323; 3 static double pi = 3.14159265358979324;
1 static double transformLat(double x, double y) 2 { 3 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)); 4 ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0; 5 ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0; 6 ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0; 7 return ret; 8 } 9 10 static double transformLon(double x, double y) 11 { 12 double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)); 13 ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0; 14 ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0; 15 ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0; 16 return ret; 17 }
1 public static float[] gcj02Encrypt(double ggLat, double ggLon) { 2 float[] resPoint = new float[2]; 3 double mgLat; 4 double mgLon; 5 double dLat = transformLat(ggLon - 105.0, ggLat - 35.0); 6 double dLon = transformLon(ggLon - 105.0, ggLat - 35.0); 7 double radLat = ggLat / 180.0 * Math.PI; 8 double magic = Math.sin(radLat); 9 magic = 1 - jzEE * magic * magic; 10 double sqrtMagic = Math.sqrt(magic); 11 dLat = (dLat * 180.0) / ((jzA * (1 - jzEE)) / (magic * sqrtMagic) * Math.PI); 12 dLon = (dLon * 180.0) / (jzA / sqrtMagic * Math.cos(radLat) * Math.PI); 13 mgLat = ggLat + dLat; 14 mgLon = ggLon + dLon; 15 16 resPoint[0] = (float) mgLat; 17 resPoint[1] = (float) mgLon; 18 return resPoint; 19 }
(2)中國國測局地理坐標(GCJ-02) 轉換成 世界標准地理坐標(WGS-84)
*******接口有1-2米左右的誤差,需要精確定位情景慎用*****
1 public static float[] gcj02Decrypt(double gjLat, double gjLon) { 2 float[] gPt = gcj02Encrypt(gjLat, gjLon); 3 double dLon = gPt[1] - gjLon; 4 double dLat = gPt[0] - gjLat; 5 float[] pt = new float[2]; 6 pt[0] = (float) (gjLat - dLat); 7 pt[1] = (float) (gjLon - dLon); 8 return pt; 9 }
(3)世界標准地理坐標(WGS-84) 轉換成 百度地理坐標(BD-09)
1 // 首先轉換獲取到GCJ-02的坐標 2 float[] gcj02Pt = gcj02Encrypt(latitude,longitude);
1 // 傳入中國國測局地理的坐標 2 public static float[] bd09Encrypt(double ggLat, double ggLon) { 3 float[] bdPt = new float[2]; 4 double x = ggLon, y = ggLat; 5 double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * Math.PI); 6 double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * Math.PI); 7 bdPt[1] = (float) (z * Math.cos(theta) + 0.0065); 8 bdPt[0] = (float) (z * Math.sin(theta) + 0.006); 9 return bdPt; 10 }
(4)中國國測局地理坐標(GCJ-02)<火星坐標> 轉換成 百度地理坐標(BD-09)
1 // 用以上辦法 2 public static float[] bd09Encrypt(double ggLat, double ggLon)
(5)百度地理坐標(BD-09) 轉換成 中國國測局地理坐標(GCJ-02)<火星坐標>
1 public static float[] bd09Decrypt(double bdLat, double bdLon) { 2 float[] gcjPt = new float[2]; 3 double x = bdLon - 0.0065, y = bdLat - 0.006; 4 double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * Math.PI); 5 double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * Math.PI); 6 gcjPt[1] = (float) (z * Math.cos(theta)); 7 gcjPt[0] = (float) (z * Math.sin(theta)); 8 return gcjPt; 9 }
(6)百度地理坐標(BD-09) 轉換成 世界標准地理坐標(WGS-84)
*******接口有1-2米左右的誤差,需要精確定位情景慎用*****
1 // 先將百度坐標 轉換成 中國國測局坐標 2 float[] gcj02 = bd09ToGcj02(latitude,longitude);
1 // 再傳入 中國國測局坐標 返回 世界標准地理坐標 2 gcj02Decrypt(gcj02[0], gcj02[1]);
