GreatMaps WinForms路线方向箭头显示问题求助
GreatMaps路线箭头方向设置与自定义三角形实现
我之前在GMap.NET(也就是你说的GreatMaps)的WinForms项目里也遇到过类似的箭头方向问题,给你分享两个可行的解决方案:
一、修复内置箭头标记的方向问题
你提到设置GMarkerGoogleType.arrow的Bearing后箭头仍朝南,核心问题是没有正确计算路线相邻点之间的方位角。内置箭头的Bearing是以正北为0度基准的顺时针旋转角度,你需要先算出两点间的行进方向,再赋值给标记。
1. 编写方位角计算函数
首先实现一个计算两个地理坐标点之间方位角的方法:
private double CalculateBearing(PointLatLng startPoint, PointLatLng endPoint) { // 转换为弧度计算 var startLatRad = startPoint.Lat * Math.PI / 180; var startLngRad = startPoint.Lng * Math.PI / 180; var endLatRad = endPoint.Lat * Math.PI / 180; var endLngRad = endPoint.Lng * Math.PI / 180; var deltaLng = endLngRad - startLngRad; var y = Math.Sin(deltaLng) * Math.Cos(endLatRad); var x = Math.Cos(startLatRad) * Math.Sin(endLatRad) - Math.Sin(startLatRad) * Math.Cos(endLatRad) * Math.Cos(deltaLng); // 转换为0-360度的角度值 var bearing = Math.Atan2(y, x) * 180 / Math.PI; return (bearing + 360) % 360; }
2. 批量添加带正确方向的箭头标记
遍历你的路线坐标列表,计算每段路径的方位角,然后创建箭头标记并设置Bearing:
// 假设routePoints是存储路线所有坐标的List<PointLatLng> int arrowInterval = 3; // 每3个点添加一个箭头,避免过于密集 for (int i = arrowInterval; i < routePoints.Count; i += arrowInterval) { var prevPoint = routePoints[i - arrowInterval]; var currentPoint = routePoints[i]; // 计算这段路径的行进方位角 double bearing = CalculateBearing(prevPoint, currentPoint); // 创建箭头标记,可选放在两点中间位置更自然 var midPoint = new PointLatLng( (prevPoint.Lat + currentPoint.Lat) / 2, (prevPoint.Lng + currentPoint.Lng) / 2 ); var arrowMarker = new GMarkerGoogle(midPoint, GMarkerGoogleType.arrow); arrowMarker.Bearing = (float)bearing; arrowMarker.Size = new Size(20, 20); // 调整箭头大小 gMapControl1.Markers.Add(arrowMarker); }
注意:GMarkerGoogle的Bearing属性是顺时针旋转角度,0度对应正北,计算出来的方位角刚好匹配这个规则,所以直接赋值即可。
二、自定义与路线描边同色的三角形箭头
如果想要和路线颜色一致的小三角形,内置箭头可能无法满足需求,这时候可以自定义一个标记类,自己绘制三角形:
1. 创建自定义箭头标记类
继承GMarker,重写OnRender方法绘制旋转后的三角形:
public class RouteArrowMarker : GMarker { private readonly Color _arrowColor; private float _bearing; public RouteArrowMarker(PointLatLng position, Color arrowColor) : base(position) { _arrowColor = arrowColor; Size = new Size(16, 16); Offset = new Point(-Size.Width / 2, -Size.Height / 2); // 让标记中心对准坐标点 } public float Bearing { get => _bearing; set { _bearing = value; Invalidate(); // 标记需要重绘 } } public override void OnRender(Graphics g) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; // 保存当前绘图状态,旋转后恢复 var graphicsState = g.Save(); // 以标记中心为旋转原点 g.TranslateTransform(Size.Width / 2, Size.Height / 2); g.RotateTransform(Bearing); // 定义三角形的三个顶点(朝上为初始方向,旋转后匹配行进方向) var trianglePoints = new[] { new Point(0, -Size.Height / 2), // 顶部点 new Point(-Size.Width / 4, Size.Height / 2), // 左下点 new Point(Size.Width / 4, Size.Height / 2) // 右下点 }; // 用路线颜色填充三角形 using (var brush = new SolidBrush(_arrowColor)) { g.FillPolygon(brush, trianglePoints); } // 恢复绘图状态 g.Restore(graphicsState); } }
2. 使用自定义标记
获取你的路线对象(比如GMapRoute)的描边颜色,然后批量添加自定义箭头:
// 假设route是你的GMapRoute实例 Color routeStrokeColor = route.Stroke.Color; int arrowInterval = 4; for (int i = arrowInterval; i < route.Points.Count; i += arrowInterval) { var prevPoint = route.Points[i - arrowInterval]; var currentPoint = route.Points[i]; double bearing = CalculateBearing(prevPoint, currentPoint); var midPoint = new PointLatLng( (prevPoint.Lat + currentPoint.Lat) / 2, (prevPoint.Lng + currentPoint.Lng) / 2 ); var customArrow = new RouteArrowMarker(midPoint, routeStrokeColor); customArrow.Bearing = (float)bearing; gMapControl1.Markers.Add(customArrow); }
这样就能得到和路线颜色完全一致的方向箭头了,你还可以调整三角形的顶点坐标、大小来优化视觉效果。
内容的提问来源于stack exchange,提问作者user2020544
相关产品推荐
相关产品推荐

