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
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Cesium Kriging是一种基于克里金插值法的三维地球表面数据插值方法,主要用于地球科学、地质勘探和空间数据分析等领域。克里金插值法是一种基于统计学原理的空间插值方法,通过分析和建立输入数据点之间的空间相关性,来预测未知地点的数值。 Cesium Kriging的主要思想是根据已知数据点之间的距离和数值变化来构建半方差函数模型,从而确定权重。然后使用这些权重对未知位置的数值进行预测与插值。在Cesium Kriging中,会分析已知数据点之间的距离和数值差异,并根据这些数据点之间的空间相关性来调整权值。 Cesium Kriging与其他插值方法相比具有以下优点: 1. 适用范围广:Cesium Kriging适用于不规则数据的插值,可以处理稀疏、非连续和不均匀分布的数据点。 2. 高精度:Cesium Kriging能够通过对空间相关性的精确建模来提供高精度的数据插值结果。 3. 不引入人为偏差:Cesium Kriging基于统计学原理,不会引入主观因素,避免了人为偏差的影响。 4. 提供插值误差估计:Cesium Kriging能够提供插值结果的误差估计,使用户能够对插值结果进行评估。 总之,Cesium Kriging是一种基于克里金插值法的三维地球表面数据插值方法,通过分析已知数据点之间的空间相关性来预测未知位置的数据,并提供高精度和误差估计的插值结果。 ### 回答2: Cesium Kriging插值是一种基于地质统计学方法的空间数据插值技术。这种技术可以通过对已知数据点进行分析和插值,来创建一个连续的表面模型。 Cesium Kriging插值方法以克里格 (Kriging) 方法为基础,克里格方法是一种通过对空间变量进行插值来推测未知地点数值的方法。Cesium Kriging插值通过对已知数据点进行拟合并创建空间模型来推测未知位置的数值。 Cesium Kriging插值方法首先建立数据之间的空间关系,通过计算已知数据点之间的空间距离和变异性,确定了不同位置之间的相关性。然后,使用这个相关性函数来估计未知位置的数值。 Cesium Kriging插值方法的优势在于它不仅可以插值数据点,还可以对未知位置进行预测,并对预测结果进行精确的空间化量化。而且,Cesium Kriging插值方法可以根据不同数据点的权重,考虑其距离和变异性,更准确地估计未知位置的数值。 Cesium Kriging插值方法在地质学、环境科学、农业和其他领域的地学研究中得到了广泛的应用。它可以用于生成高质量的地学地图,评估地下水资源,预测环境变量的分布等。 综上所述,Cesium Kriging插值是一种利用地质统计学方法进行空间数据插值的技术。它通过建立数据之间的空间关系,并使用克里格方法来估计未知位置的数值。其优势在于可以预测未知位置的数值并提供空间化量化。这种方法在地质学和其他地学研究中具有广泛应用。 ### 回答3: Cesium Kriging插值是一种在地质和地球科学领域常用的一种空间插值方法。它基于克里格(Kriging)算法和Cesium地球可视化引擎,用于在地球表面上点之间进行离散数据的插值Cesium Kriging插值的基本原理是根据采样点之间的空间位置和变量值的相关性来预测未采样点的值。它使用了变异函数和半方差模型来描述采样点之间的空间相关性。变异函数定义了变量值随着空间距离的变化规律,半方差模型则用于拟合这个变异函数。通过预测未采样点的值,Cesium Kriging插值可以在空间上生成连续的表面。 Cesium Kriging插值方法的优点是可以充分利用采样点之间的空间关系,能够更准确地预测未采样点的值。同时,Cesium地球可视化引擎的应用使得插值结果可以以更直观的方式展示在地球表面上。这种方法在地质勘探、地质灾害评估和自然资源管理等领域有着广泛的应用。 然而,Cesium Kriging插值也有一些限制。首先,它要求采样点之间存在一定的空间相关性,在采样密度较低的地区效果可能不理想。其次,插值结果可能会受到离群值的影响,需要进行一定的预处理或者异常值检测。最后,Cesium Kriging插值方法对于大规模数据集的处理可能会比较耗时,需要考虑计算效率的问题。 综上所述,Cesium Kriging插值是一种常用的空间插值方法,可以用于预测未采样点的值,并以直观的方式展示在地球表面上。它在地质和地球科学的研究中具有广泛的应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值