GPS平台,需要和各種地圖打交道,需要解決以下的問題:
1.坐標偏移,這個不用多說,需要將原始坐標加偏,然后在百度地圖或谷歌上顯示出來,需要注意的是百度地圖的加偏是偏上再偏,谷歌、高德地圖等是火星坐標;
2.坐標解偏,或者糾偏,這個我們也是需要的,因為當用戶在地圖上畫出的各種區域,標注,發送到后台存儲的坐標都是基於地圖所采用的坐標系統,因而是偏移的,這就面臨一個嚴重的問題,因為在部標808協議中,對於區域報警,需要將區域的頂點坐標,下發給終端,終端在實際運行中,不斷用GPS坐標和區域坐標進行比對,來判斷是否是進入區域報警,還是離開區域報警。如果區域坐標是偏移的,那么判斷出來必然是錯誤的。所以下發前,必須要將偏移的坐標逆向再還原成原始的基於wgs84坐標系的坐標出來。
3.區域報警,GPS部標平台也要求平台支持區域報警,也就是說,如果終端沒有這個功能,平台也是可以自己來分析GPS位置,來進行區域報警。那么部標平台就要提供圓形、多邊形、矩形區域的判斷算法。
4.路線偏移,部標規定部標平台在過檢測的時候,必須要測試路線偏移報警,所以部標平台也要提供路線偏移的判斷算法。
5.地理位置,用戶需要知道車輛的地理位置的文字信息,需要知道報警時的具體地點,很多平台在報表中僅僅顯示了個經緯度坐標,這個是很讓人惱火的。所以在后台需要提供獲取地理位置的接口,在報警的時候,記錄下地理位置。保存到數據庫中,再形成報表顯示。
6.通常的GPS平台,都會提供至少兩個地圖給用戶使用,如百度、四維、谷歌、高德等,我們的算法必須要使用與所有這些地圖。
所以我們在設計的過程中,堅決屏棄掉掉遠程調用百度地圖SDK http接口之類的方法,因為無法容忍Http調用的次數限制、性能損失和網絡問題帶來的Timeout等不可預料的未知錯誤,所以堅決設計一個底層的算法服務庫,提供給其他開發人員使用,因為是純算法,上本地可以無限次調用,也不用擔心性能問題,在開發方法上由於是直接調用轉換,對於程序員開發效率也是大大提升。
解決了最難解決的百度坐標加偏和反向糾偏的問題,純算法代碼,不調用百度地圖的SDK API,而且提供了百度所沒有的反向糾偏的算法,可以將手機百度地圖的坐標直接反向解析成原始GPS坐標(wgs84坐標系)。
百度地圖、谷歌地圖、高德地圖、四維地圖、GPS終端設備坐標直接可以靈活互轉,再也不用受限於遠程調用http接口的性能損失和網絡中斷的麻煩。
現在提供了一個在線的動態庫(如需購買,離線DLL300元,源碼600元)
調用方法如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MapServiceClient;
using MapServiceClient.MapFix;
using GpsNET.CoordService;
using GpsNET;
namespace MapServiceDemo
{
/**
*@author www.ltmonitor.com
*@email speed.zheng@gmail.com
*/
class Program
{
static void Main(string[] args)
{
MapServiceClient.MapFix.IMapService service = MapServiceFactory.getMapService();
double lng1 = 121.111;
double lat1 = 32.121;
//獲取地理位置
String location = service.GetLocation(lng1, lat1);
Console.WriteLine(location);
//測試點是否在圓形區域中
double centerLng = 120;
double centerLat = 32;//圓心坐標
double radiusByMeter = 100;//圓形半徑,米為單位
Boolean isInCircle = service.IsInCircle(lng1, lat1, centerLng, centerLat, radiusByMeter);
//測試點是否在多邊形中
MyPointLatLng p = new MyPointLatLng(lat1, lng1);
MyPointLatLng p1 = new MyPointLatLng(33.12,121.10);
MyPointLatLng p2 = new MyPointLatLng(33.12, 121.10);
MyPointLatLng p3 = new MyPointLatLng(33.12, 121.10);
MyPointLatLng p4 = new MyPointLatLng(33.12, 121.10);
MyPointLatLng[] points = new MyPointLatLng[]{p1,p2,p3};//多邊形的頂點
Boolean isInPolygon = service.IsInPolygon(p, points);
//測試點是否在矩形中,矩形的左上角和右下角的坐標必須要輸入正確,不能搞混
//Boolean isInRect = service.IsInRect(lng1,lat1,lngLeft, latTop,lngRight,latBottom);
int offset = 12;//路線偏移的最大距離
Boolean isOnline = service.IsPointOnLine(p, p1, p2, offset);
//測試坐標加偏和解偏
for (int m = 0; m < 50; m++)
{
double lng = 121.122 + m * 0.01;
double lat = 33.222 + m * 0.01;
//百度坐標加偏
MyPointLatLng pt1 = service.Fix(lng, lat, "baidu");
/**
*反向還原成原始的GPS坐標
*/
MyPointLatLng pt2 = service.Reverse(pt1.Lng, pt1.Lat, "baidu");
/**
* 獲得兩點之間的誤差距離,單位米
*/
double d = service.GetDistanceByMeter(lng, lat, pt2.Lng, pt2.Lat);
Console.WriteLine("百度坐標還原后,兩點之間的誤差精度:" + d + "米");
//火星坐標系(如谷歌,高德)坐標加偏
pt1 = service.Fix(lng, lat, "google");
/**
*反向還原成原始的GPS坐標
*/
pt2 = service.Reverse(pt1.Lng, pt1.Lat, "google");
/**
* 獲得兩點之間的誤差距離,單位米
*/
d = service.GetDistanceByMeter(lng, lat, pt2.Lng, pt2.Lat);
Console.WriteLine("谷歌坐標還原后,兩點之間的誤差精度:" + d + "米");
}
Console.ReadLine();
}
}
}
原始坐標,和經過加偏再解偏后的坐標比較,誤差精度在1米左右,非常精確。運行結果如下:

