在Gmap.Net.WinformsMap中显示路线方向

s8vozzvw  于 12个月前  发布在  .NET
关注(0)|答案(1)|浏览(128)

我正在使用Gmap.Net.Winforms来显示winform项目中的路由路径列表中存在的路由。我在Map上正确地显示了路由路径,但现在我想在这些路由路径上通过箭头来显示方向路径。我不知道如何在路径上正确地显示从第一个点到下一个点的路径。我想也许我应该使用两点之间的Angular ,但不知道怎么用

for (int i = 1; i < mainPoints.Count; i++)
       {
           double lat = (mainPoints[i - 1].Lat + mainPoints[i].Lat) / 2;
           double lng = (mainPoints[i - 1].Lng + mainPoints[i].Lng) / 2;

           double xDiff = mainPoints[i-1].Lat + mainPoints[i].Lat;
           double yDiff = mainPoints[i-1].Lng + mainPoints[i].Lng;
           double degree = Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI;

           GMarkerCross cm = new GMarkerCross(new PointLatLng(lat, lng));
           cm.Pen = new Pen(System.Drawing.Color.Transparent);
                   
           cm.ToolTipText = ">";
 
           cm.ToolTip.Offset = new System.Drawing.Point(0, 0);
           cm.ToolTip.Font = new Font("Comic Sans MS", 25f, FontStyle.Bold | FontStyle.Italic);
           cm.ToolTip.Foreground = new SolidBrush(System.Drawing.Color.Red);
           cm.ToolTip.Fill = new SolidBrush(System.Drawing.Color.Transparent);
           cm.ToolTipMode = MarkerTooltipMode.Always;
           cm.ToolTip.Stroke = new Pen(System.Drawing.Color.Transparent);
           markersLayer.Markers.Add(cm);
         }

gmap.ZoomAndCenterRoute(route);

字符串

qvtsj1bj

qvtsj1bj1#

首先选择一个合适的形状来显示方向,最好是透明背景:

然后把这个形状作为自定义标记在中点。所选的形状方向是向上的,这意味着当方位为零时(即朝向北极)需要零旋转。

计算中点:

public const double k = Math.PI / 180d; // degrees to radians

public PointLatLng MidPoint(PointLatLng point1, PointLatLng point2)
{
    // Returns the half-way point along a great circle path between the two points.
    // https://www.movable-type.co.uk/scripts/latlong.html

    // Bx = cos φ2 ⋅ cos Δλ
    // By = cos φ2 ⋅ sin Δλ
    // φm = atan2(sin φ1 + sin φ2, √(cos φ1 + Bx)² +By² )
    // λm = λ1 + atan2(By, cos(φ1) + Bx)

    double φ1 = point1.Lat * k;
    double λ1 = point1.Lng * k;
    double φ2 = point2.Lat * k;
    double λ2 = point2.Lng * k;

    double Bx = Math.Cos(φ2) * Math.Cos(λ2 - λ1);
    double By = Math.Cos(φ2) * Math.Sin(λ2 - λ1);
    double φm = Math.Atan2(Math.Sin(φ1) + Math.Sin(φ2),
        Math.Sqrt(Math.Pow((Math.Cos(φ1) + Bx), 2d) + By * By));
    double λm = λ1 + Math.Atan2(By, Math.Cos(φ1) + Bx);
    return new PointLatLng(φm / k, λm / k);
}

字符串

计算方位:

public double Bearing(PointLatLng point1, PointLatLng point2)
{
    // returns bearing between to points in radians
    // https://www.movable-type.co.uk/scripts/latlong.html

    // θ = atan2(sin Δλ ⋅ cos φ2, cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ)

    double φ1 = point1.Lat * k;
    double λ1 = point1.Lng * k;
    double φ2 = point2.Lat * k;
    double λ2 = point2.Lng * k;
    double y = Math.Sin(λ2 - λ1) * Math.Cos(φ2);
    double x = Math.Cos(φ1) * Math.Sin(φ2) - Math.Sin(φ1) * Math.Cos(φ2) * Math.Cos(λ2 - λ1);
    return Math.Atan2(y, x);
}

旋转形状:

public Bitmap RotateShape(Bitmap shape, double angle) // angle in radians
{
    Bitmap bmp = new Bitmap(shape.Width, shape.Height);
    bmp.SetResolution(shape.HorizontalResolution, shape.VerticalResolution);
    using (Graphics g = Graphics.FromImage(bmp))
    {
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.TranslateTransform(shape.Width / 2, shape.Height / 2);
        g.RotateTransform((float)(angle / k));
        g.TranslateTransform(-shape.Width / 2, -shape.Height / 2);
        g.DrawImage(shape, new Point(0, 0));
    }
    return bmp;
}

样本数据:

PointLatLng[] coords = new PointLatLng[]
{
    new PointLatLng(22.314829392513598, 114.05459908390375),
    new PointLatLng(22.314861593596778, 114.05412482777214),
    new PointLatLng(22.314644236141167, 114.05375064403528),
    new PointLatLng(22.314535557286437, 114.05350263853526),
    new PointLatLng(22.313847255908490, 114.05338951321947),
    new PointLatLng(22.313706375091120, 114.05441199203533),
    new PointLatLng(22.313223354066515, 114.05435978035109),
    new PointLatLng(22.313162976320920, 114.05468610337743),
    new PointLatLng(22.313122724476038, 114.05478182479850),
    new PointLatLng(22.312893288738540, 114.05462083877217),
    new PointLatLng(22.312720205388830, 114.05442504495637),
    new PointLatLng(22.312893288738540, 114.05322852719314),
    new PointLatLng(22.313142850399935, 114.05328073887735)
};

绘制路线,在每个线段的中点插入方向,并与线段Angular 对齐:

private void draw_path()
{
    gmap.MapProvider = GMapProviders.GoogleMap; ;
    GMaps.Instance.Mode = AccessMode.ServerOnly;

    GMapOverlay routeLayer = new GMapOverlay("routes");
    GMapRoute route = new GMapRoute(coords, string.Empty); 
    routeLayer.Routes.Add(route);
    gmap.Overlays.Add(routeLayer);

    GMapOverlay markersLayer = new GMapOverlay("markers");
    markersLayer.Id = "markers";

    GMarkerGoogle gm_start = new GMarkerGoogle(coords[0], GMarkerGoogleType.red);
    gm_start.ToolTipText = "Start";
    gm_start.ToolTipMode = MarkerTooltipMode.Always;
    markersLayer.Markers.Add(gm_start);
    
    GMarkerGoogle gm_end = new GMarkerGoogle(coords[coords.Length - 1], GMarkerGoogleType.red);
    gm_end.ToolTipText = "End";
    gm_end.ToolTipMode = MarkerTooltipMode.Always;
    markersLayer.Markers.Add(gm_end);

    for (int i = 1; i < coords.Length; i++)
    {
        using (Bitmap arrow = Resources.a1)
        {
            GMarkerGoogle gm = new GMarkerGoogle(
                p: MidPoint(coords[i - 1], coords[i]),
                bitmap: RotateShape(arrow, (float)(Bearing(coords[i - 1], coords[i])))
                );
            gm.Offset = new Point(-arrow.Width / 2, -arrow.Height / 2);
            markersLayer.Markers.Add(gm);
        }
    }

    gmap.Overlays.Add(markersLayer);
    gmap.ZoomAndCenterRoute(route);
}

结果:

放大视图:

相关问题