当前位置:   article > 正文

GMap 自定义绘图

gmap.net 绘制图片
GMap自定义绘图

gmap自带的绘图只难绘制路径,多边形,固定大小的圆.在实际开发中可能这些并不能满足自己所需.这里就需要自定义绘图
原理:继承GMapRoute或者GMapMarker类,重写里面的OnRender函数.在OnRender函数里重新绘制所需的图形即可,OnRender函数里传参的是(Graphics g) 这是微软自己的类,可以在msdn上找到完整的绘图说明.相信用过c#绘图的同学一定很熟悉
GMapRoute和GMapMarker和区别在于,GMapRoute的构造函数是可以传一个PointLatLng链表进去,它的基类有自动将链表里甩的GPS坐标点全部转换为屏幕坐标系下的坐标点.以便使用Graphics进行绘图.而GMapMarker每次只能传参一个坐点进去,因为它目地只是为了操作一个点
下面帖上两段代码,继承GMapRoute的类是实现了在线上加了箭头,指明了路径的方向
继承GMapMarker的类是实现画圆,同时也实现在圆上指明了方向

说明:由于获取三角形三个点坐标使用到的向量,因此需要添加引用 System.Numerics.Vectors
建议使用NuGet安装
在NuGet中搜索 System.Numerics.Vectors ,下载第一个安装即可
1608155-20190707170205992-906950247.png

  1. namespace gMapActiveX.CustomMarkers
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Drawing;
  6. using System.Drawing.Drawing2D;
  7. using System.Runtime.Serialization;
  8. using System.Windows.Forms;
  9. using GMap.NET;
  10. using GMap.NET.WindowsForms;
  11. /// <summary>
  12. /// GMap.NET route
  13. /// </summary>
  14. [Serializable]
  15. class MyGMapRoute : GMapRoute, ISerializable
  16. {
  17. /// <summary>
  18. /// specifies how the outline is painted
  19. /// </summary>
  20. [NonSerialized]
  21. public Pen MyStroke = DefaultStroke;//使用默认线属性
  22. public Brush Fill = new SolidBrush(Color.Yellow);//填充属性,用于箭头
  23. public int R = 14;//圆点半径
  24. public int Length = 20;//箭头三角形的宽度
  25. public bool TriangleIsVisible = true;//是否带箭头
  26. public bool DotIsVisible = true;//是否启用圆点
  27. static MyGMapRoute()
  28. {
  29. DefaultStroke.LineJoin = LineJoin.Round;
  30. DefaultStroke.Width = 5;
  31. }
  32. public MyGMapRoute(string name)
  33. : base(name)
  34. {
  35. }
  36. public MyGMapRoute(IEnumerable<PointLatLng> points, string name)
  37. : base(points, name)
  38. {
  39. }
  40. public MyGMapRoute(MapRoute oRoute)
  41. : base(oRoute)
  42. {
  43. }
  44. public override void OnRender(Graphics g)
  45. {
  46. if (IsVisible)
  47. {
  48. List<Point[]> pointsList = new List<Point[]>();
  49. Point[] pnts = new Point[LocalPoints.Count];
  50. for (int i = 0; i < LocalPoints.Count; i++)
  51. {
  52. Point p2 = new Point((int)LocalPoints[i].X, (int)LocalPoints[i].Y );
  53. pnts[pnts.Length - 1 - i] = p2;
  54. }
  55. if (pnts.Length > 1)
  56. {
  57. g.DrawLines(Stroke, pnts);
  58. for (int i = 1; i < pnts.Length; i++)
  59. {
  60. if(TriangleIsVisible)
  61. {
  62. Transfrom.GetTriangle(pnts[pnts.Length - 1 - i + 1], pnts[pnts.Length - 1 - i], Length, out PointF[] points);
  63. g.FillPolygon(Fill, points);//画箭头
  64. }
  65. if(DotIsVisible)
  66. {
  67. g.FillEllipse(Fill, new Rectangle(pnts[pnts.Length - 1 - i].X - R / 2, pnts[pnts.Length - 1 - i].Y - R / 2, R, R));
  68. }
  69. }
  70. if(DotIsVisible)
  71. {
  72. g.FillEllipse(Fill, new Rectangle(pnts[pnts.Length - 1].X - R / 2, pnts[pnts.Length - 1].Y - R / 2, R, R));
  73. }
  74. }
  75. }
  76. }
  77. /// <summary>
  78. /// 释放颜色及资源
  79. /// </summary>
  80. #region IDisposable Members
  81. bool disposed = false;
  82. public override void Dispose()
  83. {
  84. if (Stroke != null)
  85. {
  86. Stroke.Dispose();
  87. Stroke = null;
  88. }
  89. if (Fill != null)
  90. {
  91. Fill.Dispose();
  92. Fill = null;
  93. }
  94. if (!disposed)
  95. {
  96. disposed = true;
  97. LocalPoints.Clear();
  98. base.Clear();
  99. }
  100. }
  101. #endregion
  102. #region ISerializable Members
  103. // Temp store for de-serialization.
  104. private GPoint[] deserializedLocalPoints;
  105. /// <summary>
  106. /// Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with the data needed to serialize the target object.
  107. /// </summary>
  108. /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data.</param>
  109. /// <param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext"/>) for this serialization.</param>
  110. /// <exception cref="T:System.Security.SecurityException">
  111. /// The caller does not have the required permission.
  112. /// </exception>
  113. public override void GetObjectData(SerializationInfo info, StreamingContext context)
  114. {
  115. base.GetObjectData(info, context);
  116. info.AddValue("Visible", this.IsVisible);
  117. info.AddValue("LocalPoints", this.LocalPoints.ToArray());
  118. }
  119. /// <summary>
  120. /// Initializes a new instance of the <see cref="GMapRoute"/> class.
  121. /// </summary>
  122. /// <param name="info">The info.</param>
  123. /// <param name="context">The context.</param>
  124. protected MyGMapRoute(SerializationInfo info, StreamingContext context) : base(info, context)
  125. {
  126. //this.Stroke = Extensions.GetValue<Pen>(info, "Stroke", new Pen(Color.FromArgb(144, Color.MidnightBlue)));
  127. this.IsVisible = Extensions.GetStruct<bool>(info, "Visible", true);
  128. this.deserializedLocalPoints = Extensions.GetValue<GPoint[]>(info, "LocalPoints");
  129. }
  130. #endregion
  131. }
  132. }
  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. namespace gMapActiveX.CustomMarkersCircle
  11. {
  12. #if !PocketPC
  13. [Serializable]
  14. public class MyGMapMarkerCircle : GMapMarker, ISerializable
  15. #else
  16. public class GMapMarkerCircle : GMapMarker
  17. #endif
  18. {
  19. /// <summary>
  20. /// In Meters 用米数确定圆
  21. /// </summary>
  22. public int Radius;
  23. /// <summary>
  24. /// 圆上是否要用箭头
  25. /// </summary>
  26. public enum Arrow {Empty,RightArrow,LeftArrow};
  27. public Arrow ArrowIsVisible = Arrow.Empty;
  28. /// <summary>
  29. /// 是否用米数确定圆
  30. /// </summary>
  31. public bool IsMeter = true;
  32. /// <summary>
  33. /// specifies how the outline is painted
  34. /// </summary>
  35. [NonSerialized]
  36. #if !PocketPC
  37. public Pen Stroke = new Pen(Color.FromArgb(155, Color.MidnightBlue));
  38. #else
  39. public Pen Stroke = new Pen(Color.MidnightBlue);
  40. #endif
  41. /// <summary>
  42. /// 圆内填充颜色
  43. /// </summary>
  44. [NonSerialized]
  45. #if !PocketPC
  46. public Brush Fill = new SolidBrush(Color.FromArgb(155, Color.AliceBlue));
  47. [NonSerialized]
  48. public Brush ArrowFill = new SolidBrush(Color.Yellow);
  49. public int Length = 20;//箭头三角形的宽度
  50. #else
  51. public Brush Fill = new System.Drawing.SolidBrush(Color.AliceBlue);
  52. #endif
  53. /// <summary>
  54. /// is filled
  55. /// </summary>
  56. public bool IsFilled = true;
  57. public MyGMapMarkerCircle(PointLatLng p,int r)
  58. : base(p)
  59. {
  60. Radius = r; // 0m
  61. IsHitTestVisible = false;
  62. }
  63. public override void OnRender(Graphics g)
  64. {
  65. int R = (int)((Radius) / Overlay.Control.MapProvider.Projection.GetGroundResolution((int)Overlay.Control.Zoom, Position.Lat)) * 2;
  66. if (IsFilled)
  67. {
  68. g.FillEllipse(Fill, new System.Drawing.Rectangle(LocalPosition.X - R / 2, LocalPosition.Y - R / 2, R, R));
  69. }
  70. g.DrawEllipse(Stroke, new System.Drawing.Rectangle(LocalPosition.X - R / 2, LocalPosition.Y - R / 2, R, R));
  71. if(ArrowIsVisible == Arrow.LeftArrow)
  72. {
  73. Transfrom.GetTriangle(new Point(LocalPosition.X + 10, LocalPosition.Y - R / 2), new Point(LocalPosition.X - 30, LocalPosition.Y - R / 2), Length, out PointF[] points);
  74. g.FillPolygon(ArrowFill, points);
  75. }
  76. if(ArrowIsVisible == Arrow.RightArrow)
  77. {
  78. Transfrom.GetTriangle(new Point(LocalPosition.X - 10, LocalPosition.Y - R / 2), new Point(LocalPosition.X + 30, LocalPosition.Y - R / 2), Length, out PointF[] points);
  79. g.FillPolygon(ArrowFill, points);
  80. }
  81. }
  82. public override void Dispose()
  83. {
  84. if (Stroke != null)
  85. {
  86. Stroke.Dispose();
  87. Stroke = null;
  88. }
  89. if (Fill != null)
  90. {
  91. Fill.Dispose();
  92. Fill = null;
  93. }
  94. base.Dispose();
  95. }
  96. public bool IsInside(PointLatLng p)
  97. {
  98. return (int)Overlay.Control.MapProvider.Projection.GetDistance(Position, p) * 1000 < Radius;
  99. }
  100. #if !PocketPC
  101. #region ISerializable Members
  102. void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
  103. {
  104. base.GetObjectData(info, context);
  105. // TODO: Radius, IsFilled
  106. }
  107. protected MyGMapMarkerCircle(SerializationInfo info, StreamingContext context)
  108. : base(info, context)
  109. {
  110. // TODO: Radius, IsFilled
  111. }
  112. #endregion
  113. #endif
  114. }
  115. }

绘制三角形,确定三个点的函数 代码参考 https://www.cnblogs.com/oY-CCTR/p/3755742.html

  1. /// <summary>
  2. /// 返回一条线的终点位置的一个三角形的三个点坐标,三角形指向线的终点
  3. /// 三角形为一个正三角形
  4. /// </summary>
  5. /// <param name="start"></param>线起始点
  6. /// <param name="end"></param>线终点
  7. /// <param name="length"></param>三角形边长
  8. /// <param name="triangle"></param>输出的三角形的三个点数组
  9. public static void GetTriangle(Point start,Point end, int length, out PointF[] triangle)
  10. {
  11. triangle = new PointF[3];
  12. if (start == end)
  13. {
  14. return;
  15. }
  16. //箭头夹角
  17. double angle = 60.0 / 180 * Math.PI;
  18. //求BE长度
  19. double widthBE = length / 2 / (Math.Tan(angle / 2));
  20. //计算箭头的尖部位置点,这里取整条线段的1/4处
  21. PointF midPoint = new PointF((3*start.X + end.X) / 4, (3*start.Y + end.Y) / 4);
  22. //起点到箭头尖的向量
  23. Vector2 lineVector = new Vector2(midPoint.X - start.X, midPoint.Y - start.Y);
  24. //箭头尖到 三角形和直线垂直点 的向量
  25. Vector2 beVector = (float)widthBE * -Vector2.Normalize(lineVector);//需用到单位向量
  26. //三角形和直线和垂直点坐标
  27. PointF ePt = new PointF();
  28. //ePt - endPt = bcVector
  29. ePt.X = midPoint.X + beVector.X;
  30. ePt.Y = midPoint.Y + beVector.Y;
  31. //三角形和直线垂直线的向量
  32. Vector2 cdVector = new Vector2(-lineVector.Y, lineVector.X);
  33. //求CE向量
  34. Vector2 ceVector = length / 2 * Vector2.Normalize(cdVector);//需用到单位向量
  35. //求C点坐标,ePt - cPt = ceVector;
  36. PointF cPt = new PointF();
  37. cPt.X = ePt.X - ceVector.X;
  38. cPt.Y = ePt.Y - ceVector.Y;
  39. //求DE向量
  40. Vector2 deVector = length / 2 * -Vector2.Normalize(cdVector);//需用到单位向量
  41. //求D点,ePt-dPt = deVector;
  42. PointF dPt = new PointF();
  43. dPt.X = ePt.X - deVector.X;
  44. dPt.Y = ePt.Y - deVector.Y;
  45. triangle[0] = midPoint;
  46. triangle[1] = dPt;
  47. triangle[2] = cPt;
  48. }

转载于:https://www.cnblogs.com/baqifanye/p/11146792.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/40412
推荐阅读
相关标签
  

闽ICP备14008679号