三维地图Cesium,加载一个模型,模型沿着给定的一组经纬度路线移动

目录

实现效果

实现思路

功能点

选择移动路线

加载模型和移动路线

重新运行

指定位置(经纬度点)开始移动

视角切换

到站提示

运行

停止

联动接口

完整代码

html

js逻辑

trainOperation.js

sourceData.js

gitee仓库项目代码

疑问解答


实现效果

三维地图Cesium,加载一个模型,模型沿着给定的一组经纬度

实现思路

  1. 车的运行使用czml文件的特性来加载小车模型和小车运行的固定路线,同时定义它们是怎么随时间的变化而变化的。
  2. 路径长度已知,运行速度已知,结合三维cesium的时钟,就可以知道火车移动完成这段路线需要的时间。
  3. 改变运行速度或改变当前移动的位置(经纬度点)发生变化,就重新计算时间,然后重新加载czml文件。

功能点

目前已经实现的功能:

1、加载指定可自定义火车模型

2、移动的路线可以自定义修改,也可以在地图上自己选择移动路线(取路线代码已有)

3、给定指定的移动速度

4、视角切换(第一视角、自由视角、跟随视角)

5、根据指定的经纬度点为起点开始移动

6、停止移动、开始移动、到站提示、从起点重新移动、默认相机的视角

7、根据实际业务,接口获取获取的速度、移动路线、车的状态(前进、静止、后退)来控制模型的状态

选择移动路线

1、方法:at3DMapGetPointTakingRoute()

2、初始化成功后,执行at3DMapGetPointTakingRoute函数

TO.at3DMapGetPointTakingRoute()

3、 打开页面,用鼠标点击需要的路线,页面会以红点的样式进行标注,每标注一个点,控制台会以数组的形式打印所有标注的点

4、 把打印数据赋值给routePath变化,完成了路线的数据采集

// 路线
export const routePath = [
    [116.44411704836098,39.95279202225133],[116.44807033296253,39.956431604742875],
    [116.45386442263022,39.952900124343756],[116.45546340934312,39.951275636111355],
    [116.45567209160625,39.9494096918938],[116.4556296095857,39.94616403625391],
]

加载模型和移动路线

加载模型和路线的方式有好几种:

    1)使用实体单独加载模型和移动路线

    2)使用czml格式描述它们两个的关系

我们这里采用第二种,之前打算用第一种,加载起来是很方便,但是需要计算模型与移动路线的关系等细节,就先不打算了。。。

具体如何使用czml文件描述模型和移动路线的关系,网上有很多,可以自行查阅。

let testModel = window.location.origin + '/Apps/SampleData/models/GroundVehicle/GroundVehicle.glb';
export function modelCzml(useRoutePath,startTime,endTime){
    let minx = startTime+'/'+endTime;
    return [
        {
            "id": "document",
            "version": "1.0"
        },
        {
            "id": "Vehicle",
            "availability": minx ,
            "label": {
                "fillColor": [
                    {
                        "rgba": [0, 0, 0, 255]
                    }
                ],
                "font": "bold 10pt Segoe UI Semibold",
                "horizontalOrigin": "CENTER",
                "outlineColor": {
                    "rgba": [0, 0, 0, 255]
                },
                "pixelOffset": {
                    "cartesian2": [40.0, 50.0]
                },
                "scale": 1.0,
                "show": [
                    {
                        "boolean": true
                    }
                ],
                "style": "FILL",
                "text": "测试火车移动",
                "verticalOrigin": "CENTER"
            },
            "model": {
                "gltf": testModel,
                "minimumPixelSize": 120,
                "maximumScale": 50
            },
            "orientation": {
                "velocityReference": "#position"
            },
            "viewFrom": {
                // "cartesian": [300, 20, 300]
                "cartesian": [500, 2000, 779]
            },
            "properties": {
                "fuel_remaining": {
                    "epoch": startTime,
                    "number": [0, 22.5, 1500, 21.2]
                }
            },
            "path": {
                "material": {
                    "solidColor": {
                        "color": {
                            "rgba": [255, 255, 0, 255]
                        }
                    }
                },
                "width": [
                    {
                        "number": 4.0
                    }
                ],
                "show": [
                    {
                        "boolean": true
                    }
                ]
            },
            "position": {
                "interpolationAlgorithm": "LAGRANGE",
                "interpolationDegree": 1,
                "wrap": false,
                "epoch": startTime,
                "cartographicDegrees": useRoutePath
                // useRoutePath:时间、经度、纬度、高度加载显示的格式为[0, 102.23404378554466, 27.825736605050523, 2500,10, 102.23691954070244, 27.82887625908256, 2500,]
            }
        }
    ]
}

重新运行

1、使用trainLoadRun()函数

2、该方法接收三个参数:

1)targetPoint:起点的经纬度,也就是路线起点

2)currentVelocity:移动速度

3)tractionMethod:火车移动状态(前进 后退 静止)

trainLoadRun(targetPoint,currentVelocity=this.currentVelocity,tractionMethod=this.tractionMethod){
        // 如果当前火车是后退,判断当前火车是否在运行路线上,如果在,则找到当前火车所在点,并反转火车路线数组
        let that = this;
        if (that.latAndLonPosition(targetPoint).exists) {
            let index = that.latAndLonPosition(targetPoint).index
            that.byLonAndLatUpdateTrainPosition(index, currentVelocity, tractionMethod)
        } else {
            console.error('当前经纬度不在轨迹运行路线上:',targetPoint)
        }
    }

指定位置(经纬度点)开始移动

也是用targetPoint方法,改变下targetPoint的位置

注意:给的经纬度点要是不在移动路线上是不做处理的

视角切换

1、第一视角

    1)相机一直在相对小车指定的位置

    2)该模式无法通过鼠标或者键盘操作地图视角

    3)路线方向变化,车的头部以及方向也随着变化

firstPerspectiveTow() {
        let that = this;
        try {
            let center = that.trainModel.position.getValue(
                that.viewer.clock.currentTime
            );
            let orientation = that.trainModel.orientation.getValue(
                that.viewer.clock.currentTime
            )
            let transform = that.Cesium.Matrix4.fromRotationTranslation(that.Cesium.Matrix3.fromQuaternion(orientation), center);
            // viewer.camera.lookAtTransform(transform, new Cesium.Cartesian3(-100, 0, 50))
            that.viewer.camera.lookAtTransform(transform, new that.Cesium.Cartesian3(-60, 0, 50))
        } catch (e) {
            console.log('err in firstPerspectiveTow function')
        }
    }

2、自由视角

    1)将viewer.trackedEntity的值为:undefined即可

viewer.trackedEntity = undefined;

3、跟随视角

viewer.trackedEntity = trainOpera.trainModel;

到站提示

根据当前已经移动的距离与总路线的距离作比较,总路线减去已经移动的路线,误差值在10米为到站,当然,这个误差值可以自己定义

arriveAtStation(clock,callBack){
        let that = this;
        let cDistance = that.walkedThrough();
        let diff = Math.abs(that.fullRoutePathDistance.total - cDistance);
        if (that.tractionMethod == '后退'){
            diff = that.fullRoutePathDistance.total - diff
        }
        if (diff < 9){
            // 可以在这里分发到站广播
            callBack && callBack();
            clock.shouldAnimate = false;
            that.arriveAatStation()
        }
    }

运行

停止

设置时钟的shouldAnimate为false即可

clock.shouldAnimate = false;

联动接口

或者的运行速度,运行状态(前进、静止、后退)等信息,通过接口的形式可以进行控制

接口数据更新的时间根据自己的事迹情况来定

如:获取接口数据的方法

// 通过接口实时获取火车运行的相关信息
    getTrainInfo() {
        let that = this;
        let res = {currentlonLat:'112.938333,40.332444',tractionMethod:'前进',speed:23}; //火车当前前进方式,3种状态:前进 后退 静止
        if (!res || res === '{}') return false;
        let currentSpeed;
        if (res.speed && res.speed.includes('km/h')){
            currentSpeed = res.speed.split('km/h')[0]  //火车运行速度
        }

        // 获取当前火车所在经纬度
        let targetPoint;

        if (res.currentlonLat){
            let point = res.currentlonLat.split(',');
            targetPoint = {lon: point[0],lat: point[1]}
        } else {
            console.log('经纬度坐标丢失');
            return false;
        }

        if (res.tractionMethod == '静止' || currentSpeed == '0'){
            that.tractionMethod = res.tractionMethod;
            that.viewer.clock.shouldAnimate = false;
            return false;
        }

        // 如果页面火车已经到了,但是接口没有返回"静止"状态,前端做停止运行动作
        if (window.isEmit && res.tractionMethod != '静止'){
            window.TO.viewer.clock.shouldAnimate = false;
            return false;
        } else {
            window.isEmit = false;
        }

        that.viewer.clock.shouldAnimate = true;

        // 运行状态不一样,要重新计算
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

草样的年华

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

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

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

打赏作者

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

抵扣说明:

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

余额充值