【轉】衆所周知地球是一個不規則橢圓體,GIS中的座標系定義由基準面和地圖投影兩組參數確定,而基準面的定義則由特定橢球體及其對應的轉換參數確定。 基準面是利用特定橢球體對特定地區地球表面的逼近,因此每個國家或地區均有各自的基準面。基準面是在橢球體基礎上建立的,橢球體可以對應多個基準面,而基準面只能對應一個橢球體。意思就是無論是谷歌地圖、搜搜地圖還是高德地圖、百度地圖區別只是針對不同的大地地理座標系標準制作的經緯度,不存在準不準的問題,大家都是準的只是參照物或者說是標準不一樣。谷歌地圖採用的是WGS84地理座標系(中國範圍除外),谷歌中國地圖和搜搜中國地圖採用的是GCJ02地理座標系,百度採用的是BD09座標系,而設備一般包含GPS芯片或者北斗芯片獲取的經緯度爲WGS84地理座標系,爲什麼不統一用WGS84地理座標系這就是國家地理測繪總局對於出版地圖的要求,出版地圖必須符合GCJ02座標系標準了,也就是國家規定不能直接使用WGS84地理座標系。所以定位大家感覺不準確很多又叫出版地圖爲火星地圖其實只是座標系不一樣而已。這就是爲什麼設備採集的經緯度在地圖上顯示的時候經常有很大的偏差,遠遠超出民用GPS 10米偏移量的技術規範,於是我們就有了谷歌地圖糾偏 騰訊搜搜糾偏 混合地圖糾偏 百度谷歌互轉存在的價值。那如何對谷歌地圖糾偏、搜搜soso地圖糾偏或者對百度地圖糾偏呢,如果用算法目前沒有太好的算法直接轉換,所以大家採用的都是比對的方法吧地球劃分成若干個小塊找到地圖的偏差量記錄下來,然後根據任意經緯度找尋最接近的偏差量加上偏差量就可以實現不同地圖之間的經緯度轉換。現在有0.01度糾偏經緯度信息,可以提供任意格式,可以直接把經緯度偏移量調整回來。百度地圖糾偏信息包含中國海域一共29,699,997條糾偏數據,谷歌地圖只包含中國陸地一共12,597,551條糾偏數據。
採用百度在線接口轉換的Java示例代碼:
protected
void
runTest()
throws
Throwable {
try
{
BaiduLocation bl =
new
BaiduLocation();
bl.gpsx =
120
;
//經度
bl.gpsy =
30
;
//緯度
GetBaiduLocation(bl);
if
(bl.ok) {
int
baidux = (
int
)(bl.baidux*1E6);
int
baiduy = (
int
)(bl.baiduy*1E6);
// 轉換成功,這個座標是百度專用的
}
else
{
/// 轉換失敗
}
}
catch
(Exception ex) {
}
}
class
BaiduLocation {
public
float
gpsx, gpsy;
public
float
baidux, baiduy;
public
boolean
ok =
false
;
}
public
static
String GetBaiduLocation(
float
x,
float
y)
throws
MalformedURLException, IOException {
String url = String.format(
"http://api.map.baidu.com/ag/coord/convert?from=0&to=4&x=%f&y=%f"
, x, y);
HttpURLConnection urlConnection = (HttpURLConnection)(
new
URL(url).openConnection());
urlConnection.connect();
BufferedReader reader =
new
BufferedReader(
new
InputStreamReader(urlConnection.getInputStream()));
String lines = reader.readLine();
reader.close();
urlConnection.disconnect();
return
lines;
}
public
static
boolean
GetBaiduLocation(BaiduLocation bl) {
try
{
bl.ok =
false
;
String res = GetBaiduLocation(bl.gpsx, bl.gpsy);
if
(res.startsWith(
"{"
) && res.endsWith(
"}"
)) {
res = res.substring(
1
, res.length() -
2
).replace(
"\""
,
""
);
String[] lines = res.split(
","
);
for
(String line : lines) {
String[] items = line.split(
":"
);
if
(items.length ==
2
) {
if
(
"error"
.equals(items[
0
])) {
bl.ok =
"0"
.equals(items[
1
]);
}
if
(
"x"
.equals(items[
0
])) {
bl.baidux = ConvertBase64(items[
1
]);
}
if
(
"y"
.equals(items[
0
])) {
bl.baiduy = ConvertBase64(items[
1
]);
}
}
}
}
}
catch
(Exception e) {
bl.ok =
false
;
}
return
bl.ok;
}
private
static
float
ConvertBase64(String str) {
byte
[] bs = Base64.decode(str);
return
Float.valueOf(
new
String(bs));
}