我正在使用Gmap.net API进行小型车辆跟踪项目。这个项目是windows形式的c#。我从以下设备获取信息:纬度,经度,速度,标题和其他一些信息。 标题信息是度(0~359),我如何能用箭头标志显示车辆在某个方向上移动?
答案 0 :(得分:2)
我知道这个线程已经差不多一年了,但这就是我根据船的方向创建一个船形标记的方法。我还根据缩放级别以不同方式绘制船。
抱歉缺少评论!
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))
答案 1 :(得分:0)
这并不像看起来那么微不足道。一种选择是简单地使用位图图像并根据需要旋转它。我需要更多的灵活性(和速度)并使用绘图功能来执行此任务。
假设您可以使用局部坐标(像素)在地图上绘制多边形,则可以手动绘制一些指标。例如,此代码:
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中采用坐标,因此您需要进行一些转换才能使其正常工作,尤其是如果您不希望位置指示器与其他所有内容一起缩放。
我希望这会有所帮助。