爲何不統一用WGS84地理座標系這就是國家地理測繪總局對於出版地圖的要求,出版地圖必須符合GCJ02座標系標準了,也就是國家規定不能直接使用WGS84地理座標系。因此定位你們感受不許確不少又叫出版地圖爲火星地圖其實只是座標系不同而已。html
以百度地圖爲例,百度地圖採用的是本身的BD09座標。若是咱們經過GPS獲取的座標,也就是WGS84座標,那麼咱們首先要將WGS座標轉換成BD09座標。代碼以下:
java
package com.jiuqi.mobile.patrol.util;android
import java.io.BufferedReader;算法
import java.io.IOException;json
import java.io.InputStreamReader;api
import java.io.OutputStream;app
import java.net.Socket;spa
import java.text.ParseException;.net
/**code
* 將真實的GPS經緯度信息轉換成百度地圖的經緯度
* */
public class GpsToBaidu {
public static void main(String args[]) throws ParseException {
String xy = changgeXY("113.684405", "34.785423");
System.out.println("------"+xy);
}
/**
* 轉換經緯度
* */
public static String changgeXY(String xx, String yy) {
try {
Socket s = new Socket("api.map.baidu.com", 80);
BufferedReader br = new BufferedReader(new InputStreamReader(s
.getInputStream(), "UTF-8"));
OutputStream out = s.getOutputStream();
StringBuffer sb = new StringBuffer(
"GET /ag/coord/convert?from=0&to=4");
sb.append("&x=" + xx + "&y=" + yy);
sb.append("&callback=BMap.Convertor.cbk_3976 HTTP/1.1\r\n");
sb.append("User-Agent: Java/1.6.0_20\r\n");
sb.append("Host: api.map.baidu.com:80\r\n");
sb
.append("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n");
sb.append("Connection: Close\r\n");
sb.append("\r\n");
out.write(sb.toString().getBytes());
String json = "";
String tmp = "";
while ((tmp = br.readLine()) != null) {
// System.out.println(tmp);
json += tmp;
}
System.out.println(json);
int start = json.indexOf("cbk_3976");
int end = json.lastIndexOf("}");
if (start != -1 && end != -1 && json.contains("\"x\":\"")) {
json = json.substring(start, end);
String[] point = json.split(",");
String x = point[1].split(":")[1].replace("\"", "");
String y = point[2].split(":")[1].replace("\"", "");
return (new String(decode(x)) + "," + new String(decode(y)));
} else {
System.out.println("gps座標無效!!");
}
out.close();
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 解碼
*
* @param str
* @return string
*/
public static byte[] decode(String str) {
byte[] bt = null;
try {
BASE64Decoder decoder = new BASE64Decoder();
bt = decoder.decodeBuffer(str);
// System.out.println(new String (bt));
} catch (IOException e) {
e.printStackTrace();
}
return bt;
}
}
若是拿到的座標是國測局座標,也就是 GCJ02,那麼使用下面方法,能夠轉換成BD09
/**
* 國測局座標和百度座標的相互轉換
*/
public class GCJToBD {
public static void main(String[] args) {
double l=113.69147;
double a=34.78425;
double lng=bd_encrypt(l, a)[0];
double lat=bd_encrypt(l, a)[1];
System.out.println(lng);
System.out.println(lat);
}
static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
/**
* 火星座標系 (國測局標準)(GCJ-02) 轉換爲百度座標系 (BD-09) 的轉換算法
* @param gg_lon
* @param gg_lat
* @return
*/
public static double[] bd_encrypt(double gg_lon,double gg_lat){
double[] d=new double[2];
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;
d[0]=bd_lon;
d[1]=bd_lat;
return d;
}
/**
* BD-09 座標轉換成GCJ-02 座標
* @param bd_lon 經度
* @param bd_lat 緯度
* @return
*/
public static double[] bd_decrypt(double bd_lon,double bd_lat)
{
double[] d=new double[2];
double x = bd_lon - 0.0065, 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_lon = z * Math.cos(theta);
double gg_lat = z * Math.sin(theta);
d[0]=gg_lon;
d[1]=gg_lat;
return d;
}
}
轉換成百度座標下的經緯度便可有在地圖上標點,固然,百度獲取的文字詳情不如高德,有時想要獲取位置詳情,須要調用高德的接口,而高德採用的標準是 GCJ02,所以,若是拿到百度地圖的經緯度或是GPS經緯度,則要轉成國測局的標準,以獲取位置詳細信息,方法以下:
//WGS84(GPS) 轉換成 GCJ02(國測局)
public class GPSToGCJ {
static double pi = 3.14159265358979324;
static double a = 6378245.0;
static double ee = 0.00669342162296594323;
// World Geodetic System ==> Mars Geodetic System
public static double[] transform(double wgLon,double wgLat) {
double[] d=new double[2];
double mgLat;double mgLon;
if (outOfChina(wgLat, wgLon)){
mgLat = wgLat;
mgLon = wgLon;
}
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 - 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);
mgLat = wgLat + dLat;
mgLon = wgLon + dLon;
d[0]=mgLon;
d[1]=mgLat;
return d;
}
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;
}
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;
}
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;
}
public static void main(String[] args) {
double l=113.68444;
double a=34.78545;
double lng=transform(l, a)[0];
double lat=transform(l, a)[1];
System.out.println(lng);
System.out.println(lat);
}
}
若是配合android端返回經緯度,百度的api中類,能夠設置返回的座標
http://developer.baidu.com/map/geosdk-android-classv3.3.htm
public void setCoorType ( String )
咱們支持返回若干種座標系,包括國測局座標系、百度座標系,須要更多座標系請聯繫咱們,須要深度合做。目前這些參數的代碼爲。所以須要在請求時指定類型,若是不指定,默認返回百度座標系。注意當僅輸入IP時,不會返回座標。目前這些參數的代碼爲
返回國測局經緯度座標系 coor=gcj02
返回百度墨卡託座標系 coor=bd09
返回百度經緯度座標系 coor=bd09ll
百度手機地圖對外接口中的座標系默認是bd09ll,若是配合百度地圖產品的話,須要注意座標系對應問題。
有關座標系的更多問題,請看常見問題