关于GMAP.NET地图控件在地图上操作的例子很多,但是关于画圆形的描述很少,我找到了GMAP官方的例子并在此基础上进行了部分的改动,实现了对GMAP地图控件的画圆操作。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Drawing; 7 using System.Runtime.Serialization; 8 using GMap.NET; 9 using GMap.NET.WindowsForms; 10 11 namespace tgmap 12 { 13 #if !PocketPC 14 [Serializable] 15 public class GMapMarkerCircle : GMapMarker, ISerializable 16 #else 17 public class GMapMarkerCircle : GMapMarker 18 #endif 19 { 20 /// <summary> 21 /// In Meters 用米数确定圆 22 /// </summary> 23 public int Radius; 24 25 /// <summary> 26 /// 用两个点确定圆 27 /// </summary> 28 public PointLatLng P2; 29 30 /// <summary> 31 /// 是否用米数确定圆 32 /// </summary> 33 public bool IsMeter = true; 34 35 36 /// <summary> 37 /// specifies how the outline is painted 38 /// </summary> 39 [NonSerialized] 40 #if !PocketPC 41 public Pen Stroke = new Pen(Color.FromArgb(155, Color.MidnightBlue)); 42 #else 43 public Pen Stroke = new Pen(Color.MidnightBlue); 44 #endif 45 46 /// <summary> 47 /// background color 48 /// </summary> 49 [NonSerialized] 50 #if !PocketPC 51 public Brush Fill = new SolidBrush(Color.FromArgb(155, Color.AliceBlue)); 52 #else 53 public Brush Fill = new System.Drawing.SolidBrush(Color.AliceBlue); 54 #endif 55 56 /// <summary> 57 /// is filled 58 /// </summary> 59 public bool IsFilled = true; 60 61 public GMapMarkerCircle(PointLatLng p) 62 : base(p) 63 { 64 Radius = 0; // 0m 65 P2 = p; 66 IsHitTestVisible = false; 67 } 68 69 public override void OnRender(Graphics g) 70 { 71 if (!IsMeter) 72 Radius = (int)Overlay.Control.MapProvider.Projection.GetDistance(Position, P2) * 1000; 73 74 int R = (int)((Radius) / Overlay.Control.MapProvider.Projection.GetGroundResolution((int)Overlay.Control.Zoom, Position.Lat)) * 2; 75 76 if (IsFilled) 77 { 78 g.FillEllipse(Fill, new System.Drawing.Rectangle(LocalPosition.X - R / 2, LocalPosition.Y - R / 2, R, R)); 79 } 80 g.DrawEllipse(Stroke, new System.Drawing.Rectangle(LocalPosition.X - R / 2, LocalPosition.Y - R / 2, R, R)); 81 } 82 83 public override void Dispose() 84 { 85 if (Stroke != null) 86 { 87 Stroke.Dispose(); 88 Stroke = null; 89 } 90 91 if (Fill != null) 92 { 93 Fill.Dispose(); 94 Fill = null; 95 } 96 97 base.Dispose(); 98 } 99 100 public bool IsInside(PointLatLng p) 101 { 102 return (int)Overlay.Control.MapProvider.Projection.GetDistance(Position, p) * 1000 < Radius; 103 } 104 105 #if !PocketPC 106 107 #region ISerializable Members 108 109 void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) 110 { 111 base.GetObjectData(info, context); 112 113 // TODO: Radius, IsFilled 114 } 115 116 protected GMapMarkerCircle(SerializationInfo info, StreamingContext context) 117 : base(info, context) 118 { 119 // TODO: Radius, IsFilled 120 } 121 122 #endregion 123 124 #endif 125 } 126 }
里面描述了两种画圆的方法,一种是根据半径(米)和Marker的Position来画圆,一种是根据Marker的Position和另外一个PointLatLng点来画圆。添加了IsInside方法来确认另一个点是否在圆内。第二种方法是为了实现鼠标点击拖动画圆,鼠标事件代码如下
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 private GMapOverlay circles = new GMapOverlay("circle"); //放置circle的图层 2 private GMapMarkerCircle drawingCircle = null; //正在画的circle 3 private bool IsDrawingCircle = false; 4 5 private void MapControl_MouseDown(object sender, MouseEventArgs e) 6 { 7 circles.Markers.Clear(); 8 IsDrawingCircle = true; 9 drawingCircle = new GMapMarkerCircle(mapControl.FromLocalToLatLng(e.X, e.Y)); 10 drawingCircle.IsMeter = false; 11 circles.Markers.Add(drawingCircle); 12 13 //polygons.Polygons.Clear(); 14 //IsDrawingPolygon = true; 15 //startX = e.X; 16 //startY = e.Y; 17 //drawingPolygon = new GMapPolygon(new List<PointLatLng>() { mapControl.FromLocalToLatLng(e.X,e.Y)}, "polygon"); 18 //polygons.Polygons.Add(drawingPolygon); 19 } 20 21 private void MapControl_MouseUp(object sender, MouseEventArgs e) 22 { 23 IsDrawingCircle = false; 24 int count = 0; 25 markersOverlay.Markers.ToList().ForEach(ma=> { 26 if (drawingCircle.IsInside(ma.Position)) 27 { 28 count++; 29 } 30 }); 31 MessageBox.Show("区域内一共有" + count + "个marker(s)"); 32 33 //IsDrawingPolygon = false; 34 //int count = 0; 35 //markersOverlay.Markers.ToList().ForEach(ma => { 36 // if (drawingPolygon.IsInside(ma.Position)) 37 // { 38 // count++; 39 // } 40 //}); 41 //MessageBox.Show("区域内一共有" + count +"个marker(s)"); 42 } 43 44 private void MapControl_MouseMove(object sender, MouseEventArgs e) 45 { 46 if (IsDrawingCircle) 47 { 48 drawingCircle.P2 = mapControl.FromLocalToLatLng(e.X,e.Y); 49 mapControl.UpdateMarkerLocalPosition(drawingCircle); 50 mapControl.Refresh(); 51 } 52 53 //if (IsDrawingPolygon) 54 //{ 55 // drawingPolygon.Points.Clear(); 56 // drawingPolygon.Points.Add(mapControl.FromLocalToLatLng(startX,startY)); 57 // drawingPolygon.Points.Add(mapControl.FromLocalToLatLng(startX, e.Y)); 58 // drawingPolygon.Points.Add(mapControl.FromLocalToLatLng(e.X, e.Y)); 59 // drawingPolygon.Points.Add(mapControl.FromLocalToLatLng(e.X, startY)); 60 // mapControl.UpdatePolygonLocalPosition(drawingPolygon); 61 // mapControl.Refresh(); 62 //} 63 }
注释的代码是我当初写拖动画矩形的部分,最终实现了鼠标放开后自动数出所画区域内Marker的数量,其实以后也可以对所有区域内的Marker进行进一步操作。
测试结果如下: