一 地圖的加載與顯示
關於GMap的介紹與使用可以看我以前的文章:
GMap.Net開發之在WinForm和WPF中使用GMap.Net地圖插件
GMap.Net是.Net下一個地圖控件,可以基於Http協議加載各個公司的地圖,如Google,Bing,ArcGIS的,主要原理是通過解析各個公司的地圖服務的URL,傳入相應的參數得到對應的切片底圖(Tiled map),如一個高德地圖的GMapProvider的實現如下:
using System; using GMap.NET; using GMap.NET.MapProviders; using GMap.NET.Projections; namespace GMapProvidersExt { public abstract class AMapProviderBase : GMapProvider { public AMapProviderBase() { MaxZoom = null; RefererUrl = "http://www.amap.com/"; //Copyright = string.Format("©{0} 高德 Corporation, ©{0} NAVTEQ, ©{0} Image courtesy of NASA", DateTime.Today.Year); } public override PureProjection Projection { get { return MercatorProjection.Instance; } } GMapProvider[] overlays; public override GMapProvider[] Overlays { get { if (overlays == null) { overlays = new GMapProvider[] { this }; } return overlays; } } } public class AMapProvider : AMapProviderBase { public static readonly AMapProvider Instance; readonly Guid id = new Guid("EF3DD303-3F74-4938-BF40-232D0595EE88"); public override Guid Id { get { return id; } } readonly string name = "AMap"; public override string Name { get { return name; } } static AMapProvider() { Instance = new AMapProvider(); } public override PureImage GetTileImage(GPoint pos, int zoom) { try { string url = MakeTileImageUrl(pos, zoom, LanguageStr); return GetTileImageUsingHttp(url); } catch (Exception ex) { return null; } } string MakeTileImageUrl(GPoint pos, int zoom, string language) { var num = (pos.X + pos.Y) % 4 + 1; //string url = string.Format(UrlFormat, num, pos.X, pos.Y, zoom); string url = string.Format(UrlFormat, pos.X, pos.Y, zoom); return url; } //static readonly string UrlFormat = "http://webrd04.is.autonavi.com/appmaptile?x={0}&y={1}&z={2}&lang=zh_cn&size=1&scale=1&style=7"; static readonly string UrlFormat = "http://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={0}&y={1}&z={2}"; } } View Code如下為高德地圖的顯示:
通過類似的辦法,可以實現加載Google、騰訊的地圖,百度的地圖也可以加載,但是因為百度采用自己的加偏算法(BD-09),導致加載的地圖顯示偏差大,當在不同的地圖間切換時,無法正確顯示。。
二 Marker的顯示與操作
GMapMarker為地圖上要顯示的數據元素,繼承GMapMarker可以實現自己想要的地圖元素效果,如下顯示自定義元素的樣式:
關於自定義Marker,可以看這篇文章:GMap.Net開發之自定義Marker,通過C# GDI+可以實現自己想要的各種圖標樣式和顯示效果。
三 圖形的顯示與操作
在地圖上手動畫各種多邊形,來實現類似“電子圍欄”的功能,可以使用GMapPolygon。
如下為我實現的圓形(Circle)、矩形(Rectangle)、多邊形(Polygon)和折線段(Polyline):
關於畫多邊形,可以看我以前的這篇文章:GMap.Net開發之在地圖上添加多邊形,手動畫多邊形時可以實時查看效果,畫完的多邊形隨地圖放大(縮小)而放大(縮小)。
實現類似百度地圖“測距”的功能:
通過點、線和提示框可以實現類似百度地圖的“測距”功能,點擊紅色的“X”,實現刪除這次測距。
四 地址解析與路徑查找
地址解析:GMap中的地址解析主要用到GeocodingProvider中的如下方法:
//根據關鍵字得到一組坐標 GeoCoderStatusCode GetPoints(string keywords, out List<PointLatLng> pointList); //根據關鍵字得到一個坐標 PointLatLng? GetPoint(string keywords, out GeoCoderStatusCode status); //根據坐標得到一組地址 GeoCoderStatusCode GetPlacemarks(PointLatLng location, out List<Placemark> placemarkList); //根據坐標得到一個地址 Placemark GetPlacemark(PointLatLng location, out GeoCoderStatusCode status);
路徑查找:GMap中的路徑查找主要用到RoutingProvider的如下方法:
//avoidHighways:是否避免走高速公路 //walkingMode:是否步行 //zoom:查找路徑時的zoom,貌似越大路徑越准確 //根據起止點start、end和當前的zoom查找路徑 MapRoute GetRoute(PointLatLng start, PointLatLng end, bool avoidHighways, bool walkingMode, int Zoom); //根據出發點地址start、目的點地址end和當前的zoom查找路徑 MapRoute GetRoute(string start, string end, bool avoidHighways, bool walkingMode, int Zoom);
接口使用方式:
RoutingProvider rp = mapControl.MapProvider as RoutingProvider; GeocodingProvider gp = mapControl.MapProvider as GeocodingProvider;
GeocodingProvider和RoutingProvider都是通過當前的MapProvider轉換得到的,也就是說如果要在加載的地圖上實現地址解析與路徑查找,就需要實現加載地圖的三大接口:
GMapProvider接口:用於顯示地圖。
RoutingProvider:用於路徑查找。
GeocodingProvider:用於地址解析。
關於地址解析與路徑查找的使用:GMap.Net開發之地址解析與路徑查找
五 地圖糾偏
中國國內的地圖都是經過“加偏”處理的,所以被稱為“火星坐標”。
現在主流的坐標系是WGS84坐標系,即地球坐標系,國際上通用的坐標系,經過國家測繪局要求采用GCJ02算法加偏後即為“火星坐標”,百度在“火星坐標”的基礎上又采用了自己的加偏算法BD09加偏後,得到“百度坐標”,國內的搜狗坐標系、圖吧坐標系等,估計也是在GCJ02基礎上加密而成的。
而現在Google中國、騰訊和高德采用的是WGS84經過GCJ02算法加偏後的“火星坐標”。
通過GPS設備采集到的坐標一般是沒有經過“加偏”處理的WGS84坐標,所以放到國內地圖上顯示會有誤差,可以把采集到的坐標也通過加偏算法加偏後再放到地圖上顯示,就可以得到對應的地點。
如下是經過加偏算法加偏後處理的情況:
如上使用Google中國地圖,現在采用的算法在地圖1-16級可以基本沒有誤差,誤差很小,當然和采集設備采集的點的准確度也有關系。
當地圖放大超過16級時候,就出現了誤差,但誤差也就在幾米:
六 中國行政區域邊界
有中國各個省市的邊界數據,就可以實現行政區域的顯示:
如下顯示江蘇省和南京市的行政邊界:
PS:現在手上有全國的各個省市縣的行政邊界,但是有幾個縣/區級的沒有。
七 地圖下載與緩存
GMap會自動在本地緩存一些訪問過的地圖,默認是不刪除的,所以當訪問的地圖區域越多時,本地的地圖緩存也就越大。
當然你也可以手動下載地圖到本地數據庫(支持SQLite、MySQL、MsSQL、PostgreSQL),如下所示:
緩存到本地的離線地圖數據就可以作為地圖數據包使用。
參考:
https://greatmaps.codeplex.com/