如何在 Gmap.Net 中显示车辆移动方向

Posted

技术标签:

【中文标题】如何在 Gmap.Net 中显示车辆移动方向【英文标题】:How to show vehicle moving direction in Gmap.Net 【发布时间】:2016-10-01 09:51:08 【问题描述】:

我正在将 Gmap.net API 用于小型车辆跟踪项目。这个项目是windows form c#。我正在从设备获取信息,例如:纬度、经度、速度、航向以及其他一些信息。 航向信息是度数(0~359),如何用箭头标志表明车辆正在向某个方向移动?

【问题讨论】:

做一个长等腰三角形并沿车辆移动的方向旋转。也许下一页上的三角形之一会有所帮助:google.com/… 【参考方案1】:

我知道这个帖子已经快一年了,但这就是我创建船标记的方式,我根据船的方向旋转。我还根据缩放级别以不同的方式绘制船。

对不起,缺少cmets!

Namespace GMap.NET.WindowsForms.Markers

Public Class GMapMarkerBoat
    Inherits GMapMarker
    Public Brush As Brush
    Public boatHeading As Double

    Public Sub New(ic As SEAS_DATA.ImageCluster, b As Brush)
        MyBase.New(ic.LatLong)
        boatHeading = ic.IMU_Heading

        Brush = b

        'Size of the marker
        Size = New Size(8, 8)

    End Sub

    Public Overrides Sub OnRender(g As Graphics)

        Dim newSize As Size
        Dim maxZoomLevel As Integer = SEAS_Forms.frmMain.myMap.MaxZoom

        Select Case SEAS_Forms.frmMain.myMap.Zoom
            Case maxZoomLevel
                newSize = New Size(Size.Width * 2, Size.Height * 2)
            Case maxZoomLevel - 1 To maxZoomLevel
                newSize = New Size(CInt(Size.Width * 1.5), CInt(Size.Height * 1.5))
            Case maxZoomLevel - 2 To maxZoomLevel - 1
                newSize = Size
            Case SEAS_Forms.frmMain.myMap.MinZoom To maxZoomLevel - 2
                newSize = New Size(CInt(Size.Width / 2), CInt(Size.Height / 2))
        End Select

        'boat
        Dim boat(4) As PointF

        boat(0).X = CSng(-newSize.Width / 2)
        boat(0).Y = CSng(-newSize.Height / 2)
        boat(1).X = (boat(0).X + newSize.Width)
        boat(1).Y = boat(0).Y
        boat(3).X = boat(0).X
        boat(3).Y = (boat(0).Y + newSize.Height)
        boat(2).X = boat(1).X
        boat(2).Y = boat(3).Y
        boat(4).X = CSng(boat(0).X - newSize.Width / 2)
        boat(4).Y = CSng(boat(0).Y + newSize.Width / 2)

        If SEAS_Forms.frmMain.myMap.Zoom > maxZoomLevel - 4 Then
            boat = TransformAndRotate(boatHeading, boat) 'simplified rotation and transformation matrix
        Else
            boat = TransformAndRotate(0, boat)
        End If

        'start drawing here
        Select Case SEAS_Forms.frmMain.myMap.Zoom
            Case maxZoomLevel - 3 To maxZoomLevel
                g.FillPolygon(Brush, boat)
            Case SEAS_Forms.frmMain.myMap.MinZoom To maxZoomLevel - 3
                Dim newRect As New RectangleF(boat(0).X, boat(0).Y, newSize.Width, newSize.Height)
                g.FillEllipse(Brush, newRect)
        End Select

    End Sub

    Private Function TransformAndRotate(heading As Double, points() As PointF) As PointF()

        Dim cosRot As Double = Math.Cos((heading + 90) * Math.PI / 180)
        Dim sinRot As Double = Math.Sin((heading + 90) * Math.PI / 180)

        For i = 0 To points.Length - 1
            Dim x As Single = points(i).X
            Dim y As Single = points(i).Y
            points(i).X = CSng((LocalPosition.X) + (x * cosRot - y * sinRot)) 'simplified rotation and transformation matrix
            points(i).Y = CSng((LocalPosition.Y) + (x * sinRot + y * cosRot))
        Next

        Return points
    End Function

End Class

End Namespace

我传入的自定义类对象(ic As ImageCluster)具有 PointLatLng 和标题的属性。

这是我添加标记的方法

'add the marker to the overlay
newOverlay.Markers.Add(New GMap.NET.WindowsForms.Markers.GMapMarkerBoat(ic, Brushes.Red))

【讨论】:

【参考方案2】:

这并不像看起来那么简单。一种选择是简单地使用位图图像并根据需要对其进行旋转。我需要更多的灵活性(和速度)并使用绘图功能来执行此任务。

假设您能够使用局部坐标(像素)在地图上绘制多边形,您可以手动绘制一些指示符。例如这段代码:

int position_size = 20; 
GPoint gp = FromLatLngToLocal(longlatposition);

Point[] pnts = new Point[4];
pnts[0] = new Point((int)gp.X - (position_size * 2), (int)gp.Y + (position_size * 2));
pnts[1] = new Point((int)gp.X, (int)gp.Y - (position_size * 4));
pnts[2] = new Point((int)gp.X + (position_size * 2), (int)gp.Y + (position_size * 2));
pnts[3] = new Point((int)gp.X, (int)gp.Y + position_size);

float heading_ = 45; //this is where you define how much to rotate
pnts = Rotate(pnts, new PointF(gp.X, gp.Y), heading_); 

g.FillPolygon(new SolidBrush(color), pnts);

将绘制一个如下所示的箭头:

旋转功能是这篇文章的一个变体:Rotate bunch of points thourgh an origin)。

private static PointF[] Rotate(PointF[] point, PointF pivot, double angleDegree)

      double angle = angleDegree * Math.PI / 180;
      double cos = Math.Cos(angle);
      double sin = Math.Sin(angle);

      PointF[] rotated = new PointF[point.Length];

      for (int i = 0; i < point.Length; i++)
      
             float dx = point[i].X - pivot.X;
             float dy = point[i].Y - pivot.Y;

             double x = (cos * dx) - (sin * dy) + pivot.X;
             double y = (sin * dx) + (cos * dy) + pivot.Y;

             rotated[i] = new PointF((float)x, (float)y);
      

      return rotated;
 

现在最困难的部分是使用 GMap 插件整合所有这些。有几种方法可以做到这一点。我个人选择修改 GMap 源代码,因为它在处理像素坐标时提供了最大的灵活性。另一个选项,假设您不想修改源,是创建一个新的多边形叠加层并在您想要显示新的位置和航向时更新点。请记住,多边形叠加层采用 lng lat 坐标,因此您需要进行一些转换才能使其正常工作,特别是如果您不希望位置指示器与其他所有内容一起缩放。

我希望这会有所帮助。

【讨论】:

以上是关于如何在 Gmap.Net 中显示车辆移动方向的主要内容,如果未能解决你的问题,请参考以下文章

gmap3:如何获得被拒绝的本地化事件?

如何旋转 GMSMarker 以显示用户移动方向?

使用内置 android 传感器的移动方向

ABAP采购订单如何取不同移动类型数量的值

如何使用一些图形在 xcode 中显示车辆的 RPM

如何在 SceneKit 中移动旋转的 SCNNode?