C# + Esri ArcGISRuntime WPF + 腾讯位置服务API实现路径规划(三)(小车跑起来)

        上篇文章中我们实现了路径计算以及在地图上的绘制,今天我们继续实现模拟车辆行驶动态效果。主要涉及到车辆匀速行驶的轨迹点以及在每个位置车辆角度的计算。

先上效果视频:

首先从网上下载个导航箭头的图片,用来当做我们地图上导航前进的symbol。

其次呢,我们需要先把这段路径下,模拟车辆行驶的所有轨迹点先计算出来,在EsriArcGIS Sdk中提供了方法,可以返回Polyline指定距离的MapPoint:

public static MapPoint CreatePointAlong(this Polyline polyline, double distance);

因为CreatPointAlong中传入的Polyline必须是投影坐标系,但我们在上篇文章中C# + Esri ArcGISRuntime WPF + 腾讯位置服务API实现路径规划(二)-CSDN博客 从API中获取到的路径,以及绘制到地图上,都是地理坐标系经纬度的Geometry,所以此处还需要多一步坐标转换(地理转投影)。

从这个网站,我们查到了高斯-克吕格投影,西安的位置所处的带号大概是:

 CGCS2000 / Gauss-Kruger zone 19 - EPSG:4497 

 

Copy出Esri WKT

传入Polyline为总路径,vehicleSpeed = 16.666m/s假设车辆行驶速度为60km/h,计算出每秒车辆行驶的轨迹点。

public static List<MapPoint> GetUniformTrajectoryPoints(Polyline polyline, double vehicleSpeed = 16.666)
{
    //CGCS2000 / Gauss-Kruger zone 19; 地理坐标系转为投影坐标系
    var convertPolyline = GeometryEngine.Project(polyline, SpatialReference.Create("PROJCS[\"CGCS2000_GK_Zone_19\",GEOGCS[\"GCS_China_Geodetic_Coordinate_System_2000\",DATUM[\"D_China_2000\",SPHEROID[\"CGCS2000\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",19500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",111.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]")) as Polyline;

    var resultPoints = new List<MapPoint>();
    var allDistance = convertPolyline.Length();
    var startIndex = 0;
    double hasDrivenDistance;
    while (true)
    {
        hasDrivenDistance = startIndex * vehicleSpeed;
        if (hasDrivenDistance >= allDistance)
        {
            resultPoints.Add(convertPolyline.CreatePointAlong(allDistance));
            break;
        }
        else
        {
            resultPoints.Add(convertPolyline.CreatePointAlong(hasDrivenDistance));
            startIndex++;
        }
    }
    return resultPoints;
}

定义导航图标的Symbol:

private PictureMarkerSymbol navigatorSymbol = new PictureMarkerSymbol(new RuntimeImage(File.ReadAllBytes(AppDomain.CurrentDomain.BaseDirectory + "\\Resource\\navigator.png")))
{
    Height = 35,
    Width = 35,
};

计算每两个轨迹点的弧度,以便导航图标的箭头角度可以与道路方向保持一致:

public static double CalculateAngle(Coordinate p0, Coordinate p1)
{
    double x = p1.Y - p0.Y;
    return Math.Atan2(p1.X - p0.X, x);
}

开始遍历每个轨迹点,绘制上图:

var allMovingPoints = CommonFunc.GetUniformTrajectoryPoints(polyLine);

for (int k = 0; k < allMovingPoints.Count; k++)
{
    var currentPoint = allMovingPoints[k];
    if (k + 1 < allMovingPoints.Count)
    {
        var nextPoint = allMovingPoints[k + 1];
        
        //计算当前点与下一个点的夹角弧度
        var angle = CommonFunc.CalculateAngle(new Coordinate
        {
            X = currentPoint.X,
            Y = currentPoint.Y
        }, new Coordinate
        {
            X = nextPoint.X,
            Y = nextPoint.Y
        });
        
        //NTS package function:  弧度转角度
        navigatorSymbol.Angle = AngleUtility.ToDegrees(angle);
        
        //将该轨迹点添加symbol
        var graphic = new Graphic(currentPoint, navigatorSymbol);
        //置顶显示
        graphic.ZIndex = 99;
        graphic.Attributes.Add("Type", "Navigator");

        //移除上一个旧的轨迹点,添加本次新的轨迹点
        var tmpOldGraphic = graphicsOverlay.Graphics.FirstOrDefault(t => t.Attributes.ContainsKey("Type"));
        graphicsOverlay.Graphics.Remove(tmpOldGraphic);
        graphicsOverlay.Graphics.Add(graphic);

        await Task.Run(() => { Thread.Sleep(10); });
    }
}

 OK,完成!

 

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

biu啊biu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值