Cesium-02:飛機模型簡單點對點飛行


Cesium-01:Vue 中基礎使用

Cesium-02:飛機模型簡單點對點飛行

Cesium-03:洪水淹沒

在上一篇文章中,對 Cesium 基本初始化有了了解。

在看了官網一些例子后,做了一個飛機根據指定路線飛行的 Demo。

飛機飛行

對於飛機飛行,主要分為以下幾個步驟。

1、模型創建

使用的飛機模型是 Cesium 官網上的,可以自行下載。

創建模型基本代碼:

      const entity = this.cesiumViewer.entities.add({
        name: 'air',
        // 放置點
        position: '',
        // 模型的朝向等
        orientation: orientation,
        // 綁定模型文件
        model: {
          uri: './model/Cesium_Air.glb',
          minimumPixelSize: 128,
          maximumScale: 20000
        },
        // 路線樣式
        path: {
          resolution: 1,
          material: new Cesium.PolylineGlowMaterialProperty({
            glowPower: 0.1,
            color: Cesium.Color.YELLOW.withAlpha(1)
          }),
          width: 3
        }
      })

2、計算路線和時間

Cesium 里面比較好的一個點就是,可以設置時間軸,設置好對應時間的坐標信息,就可以控制飛行了。

所以這里就是計算路線和時間,並把這兩信息做一一對應。

下面是寫的一個簡單的路徑計算函數:

    computeFly() {
      // 位置參考和方向等信息的存儲
      const property = new Cesium.SampledPositionProperty()

      // 起點:杭州城西
      const startPoint = [119.966746, 30.270928]
      // 終點:錢江新城
      const endPoint = [120.220684, 30.26294]

      this.height = 500
      const length = 100
      const lonAvg = (endPoint[0] - startPoint[0]) / length
      const latAvg = (endPoint[1] - startPoint[1]) / length
      for (let index = 0; index < length; index++) {
        const time = Cesium.JulianDate.addSeconds(this.startTime, 3.6 * index, new Cesium.JulianDate())
        const position = Cesium.Cartesian3.fromDegrees(startPoint[0] + lonAvg * index, startPoint[1] + latAvg * index, this.height)
        property.addSample(time, position)
      }
      return property
    }

3、調整飛行視角

經過上面兩部,基本的工作已經完成了。

把對應的路線、方向信息綁定到模型。

此時雖然可以飛了,但是飛機的視角並不是很好。

主要是設置 entity 的 viewFrom 。

這里又兩個點:

a)賦值的是迪卡爾4系坐標(這里可以區路線中的第一個位置向量)

b)這個坐標系是相對的,相對於模型的中心點

 

4、全部代碼

下面是全部的代碼:

<template>
  <div id="cesiumContainer" class="cesium-box" />
</template>

<script>
import 'cesium/Build/Cesium/Widgets/widgets.css'
import * as Cesium from 'cesium'

const googleMap = 'https://mt0.google.com/vt/lyrs=s&x={x}&y={y}&z={z}'

export default {
  name: 'App',
  data() {
    return {
      cesiumViewer: null,
      homeView: null,
      startTime: null,
      stopTime: null,
      height: 4000
    }
  },
  created() {
    this.homeView = {
      destination: Cesium.Cartesian3.fromDegrees(119.966746, 30.270528, this.height + 500),
      orientation: {
        // 航向
        heading: Cesium.Math.toRadians(0),
        // 俯仰
        pitch: Cesium.Math.toRadians(-60),
        // 滾轉
        roll: 0.0
      },
      // camera 初始化后回調函數
      complete: this.createModel
    }

    this.startTime = Cesium.JulianDate.fromDate(new Date('2021-11-08 16:00:00'))
    this.stopTime = Cesium.JulianDate.addSeconds(this.startTime, 360, new Cesium.JulianDate())
  },
  mounted() {
    this.cesiumViewer = new Cesium.Viewer('cesiumContainer', {
      infoBox: false,
      imageryProvider: new Cesium.UrlTemplateImageryProvider({ url: googleMap })
    })

    // 設置時間軸基本信息
    this.cesiumViewer.clock.startTime = this.startTime.clone()
    this.cesiumViewer.clock.currentTime = this.startTime.clone()
    this.cesiumViewer.clock.stopTime = this.stopTime.clone()
    this.cesiumViewer.clock.multiplier = 10
    this.cesiumViewer.timeline.zoomTo(this.startTime, this.stopTime)
    this.cesiumViewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP

    // 初始化視角(飛行模式)
    this.cesiumViewer.camera.flyTo(this.homeView)

    // 重寫 homeButton 事件
    this.cesiumViewer.homeButton.viewModel.command.beforeExecute.addEventListener((e) => {
      // 阻止事件繼續傳遞
      e.cancel = true
      this.cesiumViewer.camera.flyTo(this.homeView)
    })
  },
  methods: {
    createModel() {
      // 計算路線
      const property = this.computeFly()
      // 取出其中的位置向量
      const orientation = new Cesium.VelocityOrientationProperty(property)
      // 取第一個位置向量,並改變相對位置(自己 new 一個也可以)
      const viewFrom = orientation.getValue(this.startTime)
      // 相對 entity 的視角坐標(迪卡爾4系坐標,可根據 entity 大小設置)
      viewFrom.z = 20 // 相對上下
      viewFrom.x = -80 // 相對前后
      const entity = this.cesiumViewer.entities.add({
        name: 'air',
        availability: new Cesium.TimeIntervalCollection([
          new Cesium.TimeInterval({ start: this.startTime, stop: this.stopTime })
        ]),
        position: property,
        orientation: orientation,
        viewFrom: viewFrom,
        model: {
          uri: './model/Cesium_Air.glb',
          minimumPixelSize: 128,
          maximumScale: 20000
        },
        path: {
          resolution: 1,
          material: new Cesium.PolylineGlowMaterialProperty({
            glowPower: 0.1,
            color: Cesium.Color.YELLOW.withAlpha(1)
          }),
          width: 3
        }
      })
      // 設置 viewer 一直跟隨 entity
      this.cesiumViewer.trackedEntity = entity
    },

    computeFly() {
      const property = new Cesium.SampledPositionProperty()

      // 起點:杭州城西
      const startPoint = [119.966746, 30.270928]
      // 終點:錢江新城
      const endPoint = [120.220684, 30.26294]

      this.height = 500
      const length = 100
      const lonAvg = (endPoint[0] - startPoint[0]) / length
      const latAvg = (endPoint[1] - startPoint[1]) / length
      for (let index = 0; index < length; index++) {
        const time = Cesium.JulianDate.addSeconds(this.startTime, 3.6 * index, new Cesium.JulianDate())
        const position = Cesium.Cartesian3.fromDegrees(startPoint[0] + lonAvg * index, startPoint[1] + latAvg * index, this.height)
        property.addSample(time, position)
      }
      return property
    }
  }
}
</script>

最后的效果如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM