经纬度绘图_用编程赋能工作系列——百度VS高德经纬度互转
上一篇剛學會了如何獲取地址所在經緯度以及經緯度對應地址,于是信心滿滿的準備在老板面前露一手,準備花點心思做個漂亮的可視化地圖放在報告亮眼的位置。
當地圖跑出來的那一刻頓時傻眼了,臥槽這些點定位的位置明顯不對呀,酒店直定位到湖里了,這讓老板看到你說后果嚴重不。
其實是因為百度地圖的經緯度和高德地圖經緯度所使用的坐標系編碼不同,所以如果你制圖的軟件或平臺是基于高德地圖服務的話,那么就需要使用對應的高德標準的經緯度來進行繪圖,同理如果你用的服務是基于百度地圖的,必須使用百度標準的經緯度坐標,如果拿到的是高德坐標則必須經過算法轉為百度標準。
今天這篇內容就給大家分享如何使用R和Python對百度坐標系和高德坐標系的經緯度進行互轉,解決地圖繪制最后一道坎兒。
內容同樣是兩個模塊四小節,使用R語言和Python分別進行百度經緯度轉高德經緯度以及高德標準轉百度,這樣我們在經緯度獲取和轉化處理上的技能掌握就比較系統了,不會再受制于工具和平臺服務的標準差異而苦惱。
一、R語言方案
1)百度經緯度轉騰訊&高德
library("leaflet") library('baidumap') library('ggplot2') library('ggmap')dt1 <- read.table(pipe("pbpaste"), sep="t", header=T,stringsAsFactors =FALSE) #百度轉騰訊&高德 bMapTransQQMap <- function (lng,lat) {x_pi = 3.14159265358979324 * 3000.0 /180.0x = lng - 0.0065y = lat - 0.006z = sqrt(x^2 + y^2) - 0.00002 * sin(y * x_pi)theta = atan2(y,x) - 0.000003 * cos(x * x_pi)lngs = z * cos(theta)lats = z * sin(theta)return(data.frame(lng,lat,lngs,lats)) }result <- bMapTransQQMap(dt1$lon,dt1$lat)使用高德地圖服務來呈現百度坐標系下的經緯度,可以看到偏移量非常明顯。
leaflet(result) %>% setView(116.2938,40.00939, zoom = 13) %>%addTiles('http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',tileOptions(tileSize=256, minZoom=9, maxZoom=17),group="高德地圖") %>%addCircleMarkers(lng = ~ lng,lat = ~lat,stroke = FALSE,fillOpacity = 1,radius =8)使用高德地圖服務來呈現經百度坐標系轉換高德坐標系后的經緯度,可以看到位置基本已經還原了。
leaflet(result) %>% setView(116.2938,40.00939, zoom = 13) %>%addTiles('http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',tileOptions(tileSize=256, minZoom=9, maxZoom=17),group="高德地圖") %>%addCircleMarkers(lng = ~ lngs,lat = ~lats,stroke = FALSE,fillOpacity = 1,radius =8)2)高德坐標系轉百度坐標系
# 騰訊&高德地圖轉百度 qqMapTransBMap <- function(lngs,lats){x_pi = 3.14159265358979324 * 3000.0 / 180.0x = lngs y = lats z = sqrt(x^2 + y^2) + 0.00002 * sin(y * x_pi)theta = atan2(y,x) + 0.000003 * cos(x * x_pi)lng_b = z * cos(theta) + 0.0065lat_b = z * sin(theta) + 0.006 return(data.frame(lngs,lats,lng_b,lat_b)) } result_b <- qqMapTransBMap(result$lngs,result$lats)使用百度地圖服務呈現高德坐標系下的經緯度,偏移情況仍然很嚴重。
options(baidumap.key = '***************') # 這里啟用的baidumap服務,后臺調用百度地圖api, # 需要使用百度api開發秘鑰,需自己申請 bjMap <- getBaiduMap(location = c(116.284028,40.001732), width = 800, height =800, zoom = 16, scale = 2 , messaging = TRUE) ggmap(bjMap) + geom_point(data = result_b, aes(x = lngs, y = lats),shape = 21 , col = 'white',fill = 'red',size = 5) +theme_nothing()使用百度地圖服務呈現經高德坐標系轉百度坐標系后的經緯度,可以看到為止基本已經還原到真實位置,誤差相對較小。
ggmap(bjMap) + geom_point(data = result_b, aes(x = lng_b, y = lat_b),shape = 21 , col = 'white',fill = 'red',size = 5) +theme_nothing()二、Python實現方案
3)百度坐標系轉高德坐標系
import pandas as pd import numpy as np import folium from folium import plugins df=pd.read_clipboard() def bMapTransQQMap(lng,lat):x_pi = 3.14159265358979324 * 3000.0 /180.0x = np.array(lng) - 0.0065y = np.array(lat) - 0.006z = np.sqrt(np.power(x,2) + np.power(y,2)) - 0.00002 * np.sin(y * x_pi)theta = np.arctan2(y,x) - 0.000003 * np.cos(x * x_pi)lngs = z * np.cos(theta)lats = z * np.sin(theta)return(pd.DataFrame({'lng':lng,'lat':lat,'lngs':lngs,'lats':lats})) result = bMapTransQQMap(df['lon'],df['lat'])使用folium庫(底層調用leaflet服務)結合高德地圖服務來呈現百度標準的的經緯度,誤差依然很大。
lng = np.array(result["lng"],dtype=float) lat = np.array(result["lat"],dtype=float) data1 = [(lat[i],lng[i]) for i in range(len(result))]map_osm = folium.Map(location=[39.996710,116.281012],zoom_start=115,tiles='http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',attr="© <a href="http://ditu.amap.com/">高德地圖</a>") marker_cluster = plugins.MarkerCluster().add_to(map_osm) for i in data1:folium.Marker(i).add_to(marker_cluster) display(map_osm)百度坐標系經轉化為高德坐標系之后,位置的精確度基本還原,明顯改善。
lng = np.array(result["lngs"],dtype=float) lat = np.array(result["lats"],dtype=float) data2 = [(lat[i],lng[i]) for i in range(len(result))]map_osm = folium.Map(location=[39.996710,116.281012],zoom_start=115,tiles='http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',attr="© <a href='http://ditu.amap.com/'>高德地圖</a>") marker_cluster = plugins.MarkerCluster().add_to(map_osm) for i in data2:folium.Marker(i).add_to(marker_cluster) display(map_osm)4)高德坐標系轉百度坐標系
#騰訊&高德地圖轉百度 def qqMapTransBMap(lngs,lats):x_pi = 3.14159265358979324 * 3000.0 / 180.0x = np.array(lngs)y = np.array(lats )z = np.sqrt(np.power(x,2) + np.power(y,2)) + 0.00002 * np.sin(y * x_pi)theta = np.arctan2(y,x) + 0.000003 * np.cos(x * x_pi)lng_b = z * np.cos(theta) + 0.0065lat_b = z * np.sin(theta) + 0.006 return(pd.DataFrame({'lngs':lngs,'lats':lats,'lng_b':lng_b,'lat_b':lat_b}))result2 = qqMapTransBMap(result['lngs'],result['lats'])至此,兩種技術方案下的所有類型轉換均以搞定,雖然至今還沒明白算法里面的具體參數到底是啥意思,只是照葫蘆畫瓢把一篇博客上的java代碼翻譯了過來(再次感謝原作者提供的java代碼),不過原理不懂沒有關系,語法能看懂就OK了。
參考資料:
https://www.cnblogs.com/wrld/p/10845870.html
總結
以上是生活随笔為你收集整理的经纬度绘图_用编程赋能工作系列——百度VS高德经纬度互转的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZZULIOJ 1066:字符分类统计
- 下一篇: OJ1050: 阶乘的累加和(C语言实现