Cesium视角插值跟踪

需求: 已知运动实体的位置信息,不同时刻相机视角更新

规划相机不同时间的视角
const geoView = {
    time: [0, 30, 158.915, 168.195, 342.995, 352.995, 600, 620, 2400, 2450, 999999999],
    heading: [86.74122015872331, 6.220334273461615, 6.220334273461615, 6.220334273461615, 6.220334273461615, 6.220334273461615, 6.220334273461615, 193.1884462729906, 193.1884462729906, 194.86485717230025, 194.86485717230025],
    pitch: [1.6260532613189567, -17.780826762364974, -17.780826762364974, -17.780826762364974, -17.780826762364974, -17.780826762364974, -17.780826762364974, -17.57337362151895, -17.57337362151895, -23.795953470748834, -23.795953470748834],
    up: [60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    range: [300, 200, 200, 150, 150, 100, 100, 100, 100, 100, 100]
}
time时间
heading偏航
pitch俯仰
up向上偏移量
range距离目标点的距离
相机视角的插值处理
for(let i = 0; i < geoView.time.length; i++){
    const time = Cesium.JulianDate.addSeconds(this.TakeoffZero, geoView.time[i], new Cesium.JulianDate())
    this.headingProperty.addSample(time, Cesium.Math.toRadians(geoView.heading[i]))
    this.pitchProperty.addSample(time, Cesium.Math.toRadians(geoView.pitch[i]))
    this.upProperty.addSample(time, geoView.up[i])
    this.rangeProperty.addSample(time, geoView.range[i])
    this.headingPropertyBack.addSample(time, Cesium.Math.toRadians(geoView.heading[i]))
    this.pitchPropertyBack.addSample(time, Cesium.Math.toRadians(geoView.pitch[i]))
    this.rangePropertyBack.addSample(time, geoView.range[i])
}

需求要求可以中途四周转向缩放,所以将偏航、俯仰、距离备份

相机按时间跟踪

有了前面两个条件,就可以开始跟踪了,注意!!!这里监听使用postRender场景渲染后再设置相机视角,否则监控的运动对象会跟不上

this.viewerListen = (scene, time) => {
    if(this.headingProperty.getValue(time) && this.pitchProperty.getValue(time) && this.rangeProperty.getValue(time)){
        const heading = this.headingProperty.getValue(time)
        const pitch = this.pitchProperty.getValue(time)
        const range = this.rangeProperty.getValue(time)
        const up = this.upProperty.getValue(time)
        const position = this.position.getValue(time)
        const ellipsoid = this.viewer.scene.globe.ellipsoid
        const cartographic = ellipsoid.cartesianToCartographic(position)
        const lon = Cesium.Math.toDegrees(cartographic.longitude)
        const lat = Cesium.Math.toDegrees(cartographic.latitude)
        const height = cartographic.height
        this.viewer.camera.lookAt(Cesium.Cartesian3.fromDegrees(lon,lat,height+up), new Cesium.HeadingPitchRange(heading, pitch, range))
    }
}
this.viewer.scene.postRender.addEventListener(this.viewerListen)
相机视角改变与复原

相机跟踪过程中更改相机,并在几秒后恢复。cesium 默认控制视角按住鼠标左键可以自由进行视角旋转,所以按下鼠标左键移除监听,抬起鼠标左键记录当前的heading和pitch,并添加指定时间后原本的视角,最后启动监听即可.

this.handler.setInputAction((e) => {
    this.viewer.scene.postRender.removeEventListener(this.viewerListen)
    this.viewerListen = null
},Cesium.ScreenSpaceEventType.LEFT_DOWN)
this.handler.setInputAction((e) => {
    const time = Cesium.JulianDate.addSeconds(this.viewer.clock.currentTime, 5, new Cesium.JulianDate())
    const timeInterval = new Cesium.TimeInterval({
        start: this.viewer.clock.currentTime,
        stop: time,
        isStartIncluded: false
    })
    const h0 = this.viewer.camera.heading
    const p0 = this.viewer.camera.pitch
    const h1 = this.headingPropertyBack.getValue(time)
    const p1 = this.pitchPropertyBack.getValue(time)
    this.headingProperty.removeSamples(timeInterval)
    this.pitchProperty.removeSamples(timeInterval)
    this.headingProperty.addSample(this.viewer.clock.currentTime, h0)
    this.pitchProperty.addSample(this.viewer.clock.currentTime, p0)
    this.headingProperty.addSample(time, h1)
    this.pitchProperty.addSample(time, p1)
    this.viewerListen = (scene, time) => {
        if(this.headingProperty.getValue(time) && this.pitchProperty.getValue(time) && this.rangeProperty.getValue(time)){
            const heading = this.headingProperty.getValue(time)
            const pitch = this.pitchProperty.getValue(time)
            const range = this.rangeProperty.getValue(time)
            const up = this.upProperty.getValue(time)
            const position = this.position.getValue(time)
            const ellipsoid = this.viewer.scene.globe.ellipsoid
            const cartographic = ellipsoid.cartesianToCartographic(position)
            const lon = Cesium.Math.toDegrees(cartographic.longitude)
            const lat = Cesium.Math.toDegrees(cartographic.latitude)
            const height = cartographic.height
            this.viewer.camera.lookAt(Cesium.Cartesian3.fromDegrees(lon,lat,height+up), new Cesium.HeadingPitchRange(heading, pitch, range))
        }
    }
    this.viewer.scene.postRender.addEventListener(this.viewerListen)
    this.postRenderListensArr.push(this.viewerListen)
},Cesium.ScreenSpaceEventType.LEFT_UP)

这里移除指定时间段的插值防止再未恢复时再次调整

鼠标滚动处理

鼠标滚动只需调整相机距离

this.handler.setInputAction(e => {
    const time0 = Cesium.JulianDate.addSeconds(this.viewer.clock.currentTime, 5, new Cesium.JulianDate())
    const time1 = Cesium.JulianDate.addSeconds(this.viewer.clock.currentTime, 10, new Cesium.JulianDate())
    const timeInterval = new Cesium.TimeInterval({
        start: this.viewer.clock.currentTime,
        stop: time1,
        isStartIncluded: false
    })
    this.rangeProperty.removeSamples(timeInterval)
    const time = this.viewer.clock.currentTime
    const range = this.rangeProperty.getValue(time)
    this.rangeProperty.addSample(time, (range - e)>=10?(range - e):10)
    this.rangeProperty.addSample(time0, (range - e)>=10?(range - e):10)
    this.rangeProperty.addSample(time1, this.rangePropertyBack.getValue(time1))
},Cesium.ScreenSpaceEventType.WHEEL)

最小为10防止穿模型,根据实际情况调整

最后完善

当我们鼠标按下时,这时相机也是在运动过程中,因此我们还需要继续跟踪

鼠标按下和抬起完整代码如下

this.handler.setInputAction((e) => {
    this.viewer.scene.postRender.removeEventListener(this.viewerListen)
    this.viewerListen = null
    this.cameraPositionListen = (scene, time) => {
        const h0 = this.viewer.camera.heading
        const p0 = this.viewer.camera.pitch
        const position = entity.position.getValue(time)
        const ellipsoid = this.viewer.scene.globe.ellipsoid
        const cartographic = ellipsoid.cartesianToCartographic(position)
        const lon = Cesium.Math.toDegrees(cartographic.longitude)
        const lat = Cesium.Math.toDegrees(cartographic.latitude)
        const height = cartographic.height
        this.viewer.camera.lookAt(Cesium.Cartesian3.fromDegrees(lon,lat,height+up), new Cesium.HeadingPitchRange(h0, p0, range))
    }
    this.viewer.scene.postRender.addEventListener(this.cameraPositionListen)
},Cesium.ScreenSpaceEventType.LEFT_DOWN)
this.handler.setInputAction((e) => {
    this.viewer.scene.postRender.removeEventListener(this.cameraPositionListen)
    this.cameraPositionListen = null
    const time = Cesium.JulianDate.addSeconds(this.viewer.clock.currentTime, 5, new Cesium.JulianDate())
    const timeInterval = new Cesium.TimeInterval({
        start: this.viewer.clock.currentTime,
        stop: time,
        isStartIncluded: false
    })
    const h0 = this.viewer.camera.heading
    const p0 = this.viewer.camera.pitch
    const h1 = this.headingPropertyBack.getValue(time)
    const p1 = this.pitchPropertyBack.getValue(time)
    this.headingProperty.removeSamples(timeInterval)
    this.pitchProperty.removeSamples(timeInterval)
    this.headingProperty.addSample(this.viewer.clock.currentTime, h0)
    this.pitchProperty.addSample(this.viewer.clock.currentTime, p0)
    this.headingProperty.addSample(time, h1)
    this.pitchProperty.addSample(time, p1)
    this.viewerListen = (scene, time) => {
        if(this.headingProperty.getValue(time) && this.pitchProperty.getValue(time) && this.rangeProperty.getValue(time)){
            const heading = this.headingProperty.getValue(time)
            const pitch = this.pitchProperty.getValue(time)
            const range = this.rangeProperty.getValue(time)
            const up = this.upProperty.getValue(time)
            const position = this.position.getValue(time)
            const ellipsoid = this.viewer.scene.globe.ellipsoid
            const cartographic = ellipsoid.cartesianToCartographic(position)
            const lon = Cesium.Math.toDegrees(cartographic.longitude)
            const lat = Cesium.Math.toDegrees(cartographic.latitude)
            const height = cartographic.height
            this.viewer.camera.lookAt(Cesium.Cartesian3.fromDegrees(lon,lat,height+up), new Cesium.HeadingPitchRange(heading, pitch, range))
        }
    }
    this.viewer.scene.postRender.addEventListener(this.viewerListen)
    this.postRenderListensArr.push(this.viewerListen)
},Cesium.ScreenSpaceEventType.LEFT_UP)

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值