前言
实现轨迹回放,GMap.NET有对应的类GMapRoute。这个类函数很少,功能有限,只能实现简单的轨迹回放。要实现更复杂的轨迹回放,就需要自己动手了。
本文介绍一种方法,可以实现复杂的轨迹回放。有句话“功夫在诗外”,GMap.NET给你提供了基本地图处理功能;但是不要让CMap.NET束缚了手脚。你需要有深刻理解地图实现原理,深入理解WPF动画的原理,才能到达随心所欲。最终的效果如下:
GMap.NET 显示原理
地图就是由许多方格“瓦片”组合而来。当你移动或缩放时,GMap.NET会根据当前位置、显示窗口、缩放级别,到地图服务器获取图片。所以地图控件本质上就是显示图片的控件,只是这些图片包含了坐标信息。
地图上加轨迹,就是在图片上画线。这些线要与gps坐标点吻合。通过GMapMarker不仅可以加标注,也可以实现轨迹。需要将gps坐标点转换成控件的坐标点,再连成线就可以了。本文就是通过GMapMarker实现了轨迹回放。
1 实现轨迹显示
通过自定义控件UserControlMapRoute实现了轨迹显示功能。需要将此控件加入到GMapMarker。
GMapMarker _routeMaker = new GMapMarker(point); UserControlMapRoute routeCtrl = new UserControlMapRoute() { Marker = _routeMaker, MapCtrl = MainMap }; routeCtrl.Init(); _routeMaker.Shape = routeCtrl; //将图层添加到地图 this.MainMap.Markers.Add(_routeMaker);
UserControlMapRoute有两个功能:显示轨迹起始点,显示轨迹。将轨迹显示功能放在类MapRoutePath中实现。该类实现的功能就是根据gps坐标显示轨迹。该类包含的变量有:
class MapRoutePath { public GMapControl MapCtrl { get; private set; } //地图控件 public Panel ParentPanel { get; private set; } //父面板,将PathRouteLine加入面板。 public Path PathRouteLine { get; private set; } //显示轨迹 List<PointLatLng> _listGpsPoint = new List<PointLatLng>(); List<Point> _listCtrlPt = new List<Point>(); public List<PointLatLng> ListGpsPoint => _listGpsPoint; //包含的gps坐标 public List<Point> ListPathPoint => _listCtrlPt; //转换成立控件坐标 }
实现轨迹功能是变量PathRouteLine,该变量的父控件是ParentPanel(就是控件UserControlMapRoute 中的根Grid控件)。MapCtrl 控件主要作用就是提供了将gps坐标转换成控件坐标的函数。
实现将gps做标注转换成控件坐标的方法:
private void ToLocalPoint() { //_listGpsPoint存储所gps坐标 _listCtrlPt存储转换后控件坐标 _listCtrlPt.Clear(); foreach (PointLatLng pt in _listGpsPoint) { Point ptGrid = ToCtrlPoint(pt); _listCtrlPt.Add(ptGrid); } } Point ToCtrlPoint(PointLatLng gpsPoint) { //转换成GMap.NET控件坐标 GPoint ptOfMapCtrl = MapCtrl.FromLatLngToLocal(gpsPoint); //GMap.NET控件坐标要转换成 控件相对于直接父面板的坐标 Point ptToMapCtrl2 = new Point(ptOfMapCtrl.X, ptOfMapCtrl.Y); Point ptOfScreen = MapCtrl.PointToScreen(ptToMapCtrl2); Point ptOfParentPanel = ParentPanel.PointFromScreen(ptOfScreen); return ptOfParentPanel; }
坐标转换过程就是: GPS坐标 –》 GMap.NET控件坐标 –》 屏幕坐标 –》 控件相对于直接父面板的坐标。获取了控件坐标,就根据这些坐标画直线就行了。
private static void CreatPath(Path path, List<Point> listPt) { if (listPt.Count <= 1) { path.Data = null; return; } PathFigure pathFigure = new PathFigure(); pathFigure.StartPoint = listPt[0]; //起始点 for (int i = 1; i < listPt.Count; i++) { //加入线段 LineSegment line = new LineSegment() { Point = listPt[i] }; pathFigure.Segments.Add(line); } PathGeometry geome<i style="color:transparent">本文来源gaodai$ma#com搞$$代**码)网8</i>try = new PathGeometry(); geometry.Figures.Add(pathFigure); path.Data = geometry; }