最近在作一個關於手機定位的小應用,需求是這樣的,用戶經過手機(Wp8)進行二維碼掃描操做而且記錄用戶的當前位置,在PC上能夠查看用戶所在地圖的位置,作法就是在用戶掃描條碼時,經過手機GPS獲取當前在地圖上的位置(採用百度靜態地圖,根據座標直接生成圖片)並將圖片保存到數據庫,PC端直接從數據庫中讀取並展現圖片。問題是:生成的圖片所呈現的位置與實際位置誤差太大。因而我開始踏上了尋找解決辦法的道路。javascript
首先我檢測個人硬件設備是否認位準確,我用WP8手機內置的地圖進行了當前位置定位,結果沒有問題,說明個人手機沒有問題。css
因爲用的是百度靜態地圖,我再次來到 百度地圖API > 常見問題 下看到這麼一條關於 座標體系:html
百度對外接口的座標系,都是通過國家測繪局加密處理,符合國家測繪局對地理信息保密要求。java
百度地圖api中採用兩種座標體系,經緯度座標系和墨卡託投影座標系。前者單位是度,後者單位是米,具體定義能夠參見百科詞條解釋: git
http://baike.baidu.com/view/61394.htm和http://baike.baidu.com/view/301981.htm。web
國際經緯度座標標準爲WGS-84,國內必須至少使用國測局制定的GCJ-02,對地理位置進行首次加密。百度座標在此基礎上,進行了BD-09二次加密措施,更加保護了我的隱私。百度對外接口的座標系並非GPS採集的真實經緯度,須要經過座標轉換接口進行轉換。 算法
座標轉換接口非公開。請將您的公司名稱、項目名稱、項目簡介、聯繫人和聯繫方式,發郵件至mapapi@baidu.com諮詢。有專人爲您解答。shell
也就是說因爲受到國家一些法律法規限制,全部的電子地圖服務提供商都須要給地圖數據加上偏移和加密,所謂的地圖數據加密偏移,其實就是用一個偏移算法對地圖的經緯度作一個加減偏移量,從而達到與實際地圖不一致。這個偏移算法自己是沒有什麼規律可言的,每家地圖服務商都有一套本身的加密偏移算法,既然算法上沒有什麼規律可言,可是對於算法中生成的偏移量是否有規律呢?這個是能夠確定的,可是偏移算法中生成的偏移量是有規律而言的。偏移量的規律很可貴到,要是能拿到這個偏移量,就能夠說是破解了某一個地圖服務商的地圖加密。
因此百度對外提供的座標系是百度本身的座標系,而手機GPS得到的是原始座標,二者不在一個座標系上,因此有很大的偏差,我測試了一下,偏差在公里以外。因此必須得把二者換成統一座標系。換成原始GPS座標在國內原則上是違法的,因此只能統一成各個地圖運營商本身的座標系,好比百度座標系或者google座標系。數據庫
如何轉換成百度座標系:官方文檔給的是:座標轉換接口非公開。因而我開始搜搜「GPS座標轉換爲百度座標」結果不負有心人吶終於找到了解決方案,特來此貼出來我整理的代碼。express
百度地圖座標轉換接口以下:
BMap.Convertor.translate(gpsPoint,0,translateCallback); //真實經緯度轉成百度座標
其中gpsPoint var gpsPoint = new BMap.Point(經度,緯度); ( GPS座標) 0:表明GPS,也能夠是2:google座標 translateCallback:回掉函數
下面是完整的測試GPS座標轉換百度座標JS源碼:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style type="text/css"> body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;} #l-map{height:100%;width:78%;float:left;border-right:2px solid #bcbcbc;} #r-result{height:100%;width:20%;float:left;} </style> <script type="text/javascript" src="http://api.map.baidu.com/api?v=1.5&ak=9fb983ecd9b505f8fedcc9ab07c65e3e"></script> <script type="text/javascript" src="http://developer.baidu.com/map/jsdemo/demo/convertor.js"></script> <title>GPS轉百度</title> </head> <body> <div id="allmap"></div> </body> </html> <script type="text/javascript"> //GPS座標 var xx = 117.126575995835; var yy = 36.6702207308909; var gpsPoint = new BMap.Point(xx,yy); //地圖初始化 var bm = new BMap.Map("allmap"); bm.centerAndZoom(gpsPoint, 15); bm.addControl(new BMap.NavigationControl()); //添加谷歌marker和label var markergps = new BMap.Marker(gpsPoint); bm.addOverlay(markergps); //添加GPS標註 var labelgps = new BMap.Label("我是GPS標註哦",{offset:new BMap.Size(20,-10)}); markergps.setLabel(labelgps); //添加GPS標註 //座標轉換完以後的回調函數 translateCallback = function (point){ var marker = new BMap.Marker(point); bm.addOverlay(marker); var label = new BMap.Label("我是百度標註哦",{offset:new BMap.Size(20,-10)}); marker.setLabel(label); //添加百度label bm.setCenter(point); alert("轉化爲百度座標爲:"+point.lng + "," + point.lat); } setTimeout(function(){ BMap.Convertor.translate(gpsPoint,0,translateCallback); //真實經緯度轉成百度座標 }, 2000); </script>
本人用C#開發的WP8應用上面JS版的不適合 因而接着查找……
找到百度的API轉換方法爲:
http://api.map.baidu.com/ag/coord/convert?from=0&to=4&x=longitude&y=latitude
其中:
from: 來源座標系 (0表示原始GPS座標,2表示Google座標)
to: 轉換後的座標 (4就是百度本身啦,好像這個必須是4才行)
x: 經度
y: 緯度
返回的結果是一個json字符串:
{"error":0,"x":"MTIxLjUwMDIyODIxNDk2","y":"MzEuMjM1ODUwMjYwMTE3"}
其中:
error:是結果是否出錯標誌位,"0"表示OK
x: 百度座標系的經度(Base64加密)
y: 百度座標系的緯度(Base64加密)
在WP8中測試源碼都已加註釋,再也不一一解釋,直接上源碼
前臺XAML頁面:
<phone:PhoneApplicationPage x:Class="Crystal.Phone.App.Page.BaiduMapConvert" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" shell:SystemTray.IsVisible="True"> <!--LayoutRoot 是包含全部頁面內容的根網格--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel 包含應用程序的名稱和頁標題--> <StackPanel Grid.Row="0" Margin="12,17,0,28"> <TextBlock Text="個人應用程序" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock Text="百度地圖" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel - 在此處放置其餘內容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Grid.RowDefinitions> <RowDefinition Height="100" /> <RowDefinition /> </Grid.RowDefinitions> <Button Name="btnConvert" Click="btnConvert_Click_1" Content="個人位置" HorizontalAlignment="Center" VerticalAlignment="Center" /> <Image x:Name="imgLocation" Stretch="Fill" Grid.Row="1"></Image> </Grid> </Grid> </phone:PhoneApplicationPage>
後臺XAML.cs
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Navigation; using Microsoft.Phone.Controls; using Microsoft.Phone.Shell; using System.IO; using Newtonsoft.Json; using Windows.Devices.Geolocation; using System.Text; using System.Windows.Media.Imaging; namespace Crystal.Phone.App.Page { public partial class BaiduMapConvert : PhoneApplicationPage { public BaiduMapConvert() { InitializeComponent(); } private async void btnConvert_Click_1(object sender, RoutedEventArgs e) { Geolocator geo = new Geolocator(); //判斷是否開啓了GPS定位 if (geo.LocationStatus == PositionStatus.Disabled) { MessageBox.Show("還沒有開啓位置服務!"); return; } Geoposition pos = await geo.GetGeopositionAsync(); //獲取當前緯度 string Latitude = pos.Coordinate.Latitude.ToString(); //獲取當前經度 string Longitude = pos.Coordinate.Longitude.ToString(); //百度座標轉換API string path = "http://api.map.baidu.com/ag/coord/convert?from=0&to=4&x=" + Longitude + "&y=" + Latitude + ""; //WebClient請求 WebClient client = new WebClient(); string strResult = await client.UploadStringTaskAsync(path,""); MapConvert mapConvert = new MapConvert(); mapConvert=JsonConvert.DeserializeObject<MapConvert>(strResult); string lon = mapConvert.x; string lat = mapConvert.y; //進行Base64解碼 byte[] xBuffer = Convert.FromBase64String(lon); string strX = Encoding.UTF8.GetString(xBuffer,0,xBuffer.Length); byte[] yBuffer = Convert.FromBase64String(lat); string strY = Encoding.UTF8.GetString(yBuffer,0,xBuffer.Length); //生成靜態圖片 string imgSrc = string.Format("http://api.map.baidu.com/staticimage?center={0},{1}&width=300&height=300&zoom=16&markers={2},{3}&markerStyles=l,A", strX, strY, strX, strY); //顯示圖片 BitmapImage bitmapImage = new BitmapImage(new Uri(imgSrc, UriKind.Absolute)); imgLocation.Source = bitmapImage; } } public class MapConvert { public string error { get; set; } public string x { get; set; } public string y { get; set; } } }
以上就是我今天整理的關於GPS座標轉換爲百度座標的方法。