前言
我最近在做一個(gè)和地圖有關(guān)的項(xiàng)目,這里本人地圖采用的是mapbox,其中涉及一個(gè)功能需要根據(jù)用戶輸入的地點(diǎn)直接定位到地圖上的對應(yīng)的位置,本人開始想的是直接調(diào)用百度的接口根據(jù)地名直接獲取坐標(biāo),發(fā)現(xiàn)在地圖上的位置有偏移不夠準(zhǔn)確,后面發(fā)現(xiàn)地圖服務(wù)之間有自己的坐標(biāo)系,不同的坐標(biāo)系之間的坐標(biāo)會有一定的偏移。
地圖的地理坐標(biāo)系
是一種球面坐標(biāo),是使用三維球面來定義地球表面位置,以實(shí)現(xiàn)通過經(jīng)緯度對地球表面點(diǎn)位引用的坐標(biāo)系,也就是說坐標(biāo)單位是經(jīng)緯度。
地球坐標(biāo)系(WGS84)
GPS,WGS-84,原始坐標(biāo)體系。一般用國際標(biāo)準(zhǔn)的GPS記錄儀記錄下來的坐標(biāo),都是GPS的坐標(biāo)。也是國際地圖提供商使用的坐標(biāo)系。但是在中國,任何一個(gè)地圖產(chǎn)品都不允許使用GPS坐標(biāo),據(jù)說是為了保密。
使用該坐標(biāo)系的在線地圖
wgs84是國際標(biāo)準(zhǔn)坐標(biāo)系,谷歌國外地圖、osm地圖等國外地圖一般是這個(gè)
火星坐標(biāo)系(GCJ-02)
國測局02年發(fā)布的坐標(biāo)體系。又稱“火星坐標(biāo)”。中國標(biāo)準(zhǔn),從國行移動設(shè)備中定位獲取的坐標(biāo)數(shù)據(jù)使用這個(gè)坐標(biāo)系。在中國,必須至少使用GCJ-02的坐標(biāo)體系。
使用該坐標(biāo)系的在線地圖
IOS地圖、谷歌國內(nèi)地圖、高德地圖、騰訊地圖
百度坐標(biāo)系(BD-09)
百度又在火星坐標(biāo)上來個(gè)二次加密,只適用于百度地圖
使用該坐標(biāo)系的在線地圖
只有百度地圖
天地圖坐標(biāo)系(CGCS-2000)
天地圖采用的是CGCS-2000坐標(biāo)系(2000坐標(biāo)系),但是因?yàn)镃GCS-2000坐標(biāo)系它與WGS84坐標(biāo)系都是地心坐標(biāo)系,因此兩者相差不大。
天地圖官網(wǎng):https://map.tianditu.gov.cn/
坐標(biāo)系轉(zhuǎn)換
如果像我這種情況一樣地圖是wgs84,卻用了百度地圖接口返回的坐標(biāo)來定位,可以對不同坐標(biāo)系的坐標(biāo)進(jìn)行轉(zhuǎn)換。下面是轉(zhuǎn)換代碼:
const x_pi = 3.14159265358979324 * 3000.0 / 180.0;
const pi = 3.1415926535897932384626;
const a = 6378245.0;
const ee = 0.00669342162296594323;
/**
* 百度坐標(biāo)系(BD-09)轉(zhuǎn)WGS坐標(biāo)
* @param {number} lng - 百度坐標(biāo)緯度
* @param {number} lat - 百度坐標(biāo)經(jīng)度
* @returns {Array} - WGS84坐標(biāo)數(shù)組 [lng, lat]
*/
function bd09towgs84(lng, lat) {
const gcj = bd09togcj02(lng, lat);
const wgs84 = gcj02towgs84(gcj[0], gcj[1]);
return wgs84;
}
/**
* WGS坐標(biāo)轉(zhuǎn)百度坐標(biāo)系(BD-09)
* @param {number} lng - WGS84坐標(biāo)系的經(jīng)度
* @param {number} lat - WGS84坐標(biāo)系的緯度
* @returns {Array} - 百度坐標(biāo)數(shù)組 [lng, lat]
*/
function wgs84tobd09(lng, lat) {
const gcj = wgs84togcj02(lng, lat);
const bd09 = gcj02tobd09(gcj[0], gcj[1]);
return bd09;
}
/**
* 火星坐標(biāo)系(GCJ-02)轉(zhuǎn)百度坐標(biāo)系(BD-09)
* @param {number} lng - 火星坐標(biāo)經(jīng)度
* @param {number} lat - 火星坐標(biāo)緯度
* @returns {Array} - 百度坐標(biāo)數(shù)組 [lng, lat]
*/
function gcj02tobd09(lng, lat) {
const z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_pi);
const theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_pi);
const bd_lng = z * Math.cos(theta) + 0.0065;
const bd_lat = z * Math.sin(theta) + 0.006;
return [bd_lng, bd_lat];
}
/**
* 百度坐標(biāo)系(BD-09)轉(zhuǎn)火星坐標(biāo)系(GCJ-02)
* @param {number} bd_lon - 百度坐標(biāo)經(jīng)度
* @param {number} bd_lat - 百度坐標(biāo)維度
* @returns {Array} - 火星坐標(biāo)數(shù)組 [lng, lat]
*/
function bd09togcj02(bd_lon, bd_lat) {
const x = bd_lon - 0.0065;
const y = bd_lat - 0.006;
const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
const gg_lng = z * Math.cos(theta);
const gg_lat = z * Math.sin(theta);
return [gg_lng, gg_lat];
}
/**
* WGS84轉(zhuǎn)GCJ02(火星坐標(biāo)系)
* @param {number} lng - WGS84坐標(biāo)系的經(jīng)度
* @param {number} lat - WGS84坐標(biāo)系的緯度
* @returns {Array} - 火星坐標(biāo)數(shù)組 [lng, lat]
*/
function wgs84togcj02(lng, lat) {
if (out_of_china(lng, lat)) {
return [lng, lat];
}
let dlat = transformlat(lng - 105.0, lat - 35.0);
let dlng = transformlng(lng - 105.0, lat - 35.0);
const radlat = lat / 180.0 * pi;
let magic = Math.sin(radlat);
magic = 1 - ee * magic * magic;
const sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi);
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * pi);
const mglat = lat + dlat;
const mglng = lng + dlng;
return [mglng, mglat];
}
/**
* GCJ02(火星坐標(biāo)系)轉(zhuǎn)GPS84
* @param {number} lng - 火星坐標(biāo)系的經(jīng)度
* @param {number} lat - 火星坐標(biāo)系緯度
* @returns {Array} - WGS84坐標(biāo)數(shù)組 [lng, lat]
*/
function gcj02towgs84(lng, lat) {
if (out_of_china(lng, lat)) {
return [lng, lat];
}
let dlat = transformlat(lng - 105.0, lat - 35.0);
let dlng = transformlng(lng - 105.0, lat - 35.0);
const radlat = lat / 180.0 * pi;
let magic = Math.sin(radlat);
magic = 1 - ee * magic * magic;
const sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi);
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * pi);
const mglat = lat + dlat;
const mglng = lng + dlng;
return [lng * 2 - mglng, lat * 2 - mglat];
}
/**
* 緯度轉(zhuǎn)換
* @param {number} lng
* @param {number} lat
* @returns {number}
*/
function transformlat(lng, lat) {
let ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * pi) + 20.0 * Math.sin(2.0 * lng * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lat * pi) + 40.0 * Math.sin(lat / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(lat / 12.0 * pi) + 320 * Math.sin(lat * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
/**
* 經(jīng)度轉(zhuǎn)換
* @param {number} lng
* @param {number} lat
* @returns {number}
*/
function transformlng(lng, lat) {
let ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * pi) + 20.0 * Math.sin(2.0 * lng * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lng * pi) + 40.0 * Math.sin(lng / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(lng / 12.0 * pi) + 300.0 * Math.sin(lng / 30.0 * pi)) * 2.0 / 3.0;
return ret;
}
/**
* 判斷是否在國內(nèi),不在國內(nèi)不做偏移
* @param {number} lng
* @param {number} lat
* @returns {boolean}
*/
function out_of_china(lng, lat) {
if (lng < 72.004 || lng > 137.8347) {
return true;
} else if (lat < 0.8293 || lat > 55.8271) {
return true;
}
return false;
}
當(dāng)然了,最好還是在開發(fā)前先調(diào)研清楚地圖的坐標(biāo)系,并去使用相同坐標(biāo)系的地圖接口服務(wù)。
總結(jié)
這是本人第一次開發(fā)地圖相關(guān)功能,也不太了解坐標(biāo)系這一概念,導(dǎo)致在開發(fā)定位功能時(shí)位置有所偏差,經(jīng)過這次學(xué)習(xí),了解到了地圖的地理坐標(biāo)系的概念以及不同地理坐標(biāo)系的區(qū)別,才發(fā)現(xiàn)定位位置偏移的問題所在,以后開發(fā)功能前也需要更詳細(xì)的去調(diào)研每塊領(lǐng)域的相關(guān)知識。文章來源:http://www.zghlxwxcb.cn/news/detail-618246.html
參考
https://www.jianshu.com/p/a5ebaa859ca1
http://t.csdn.cn/IiuP2文章來源地址http://www.zghlxwxcb.cn/news/detail-618246.html
到了這里,關(guān)于一文講清楚地圖地理坐標(biāo)系的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!