iClent3D for Cesium 实现无人机巡检飞行效果

作者:gaogy

1、背景

随着地理信息技术的发展,三维地球技术逐渐成为了许多领域中的核心工具,尤其是在城市规划、环境监测、航空航天以及军事领域。三维地图和场景的应用正在帮助人们更加直观地理解空间数据,提供更高效的决策支持。

iClient3D for Cesium 是由 SuperMap 提供的一款开发工具,旨在将三维地理信息系统 (3D GIS) 技术应用于大规模的地理信息可视化与分析,帮助开发者通过 Web 平台展示三维地图,还提供了强大的数据分析功能,包括对建筑物、地形、设施等的空间分析。

本文将利用 iClient3D for Cesium 实现三维场景下的无人机巡检飞行效果,模拟无人机的飞行,并能将无人机拍摄范围以光源形式实时展示于三维场景之中,为低空经济与发展提供有效的无人机可视化飞行效果。

2、无人机飞行效果演示

iClent3D for Cesium 实现无人机巡检飞行效

3、实现过程

3.1、初始化 viewer 场景

js 复制代码
function initViewer(viewerContainer) {
  window.viewer = new Cesium.Viewer(viewerContainer, {
    shouldAnimate: true,
    useDefaultRenderLoop: true,
    infoBox: false,
    contextOptions: {
      webgl: {
        alpha: false,
        antialias: true,
        preserveDrawingBuffer: true,
        failIfMajorPerformanceCaveat: false,
        depth: true,
        stencil: false,
        anialias: false
      }
    }
  })
  viewer.imageryLayers.addImageryProvider(
    new Cesium.BingMapsImageryProvider({
      url: 'https://dev.virtualearth.net',
      mapStyle: Cesium.BingMapsStyle.AERIAL,
      key: 'AiCyZH6DplpqBK5CViec7lYcLq941OtnIAvlcVojsyxBfZwUDvp0CsHzZr--U2KY'
    })
  )
  viewer.scene.open('http://www.supermapol.com/realspace/services/3D-CBD/rest/realspace')
}

3.2、自定义 Cesium 飞行 Entity 的 vue hook 如下:

js 复制代码
import { onMounted } from 'vue'

function getDirection(tagPosition, position) {
  return Cesium.Cartesian3.normalize(
    Cesium.Cartesian3.subtract(tagPosition, position, new Cesium.Cartesian3()),
    new Cesium.Cartesian3()
  )
}

function getModelGraphics(options) {
  if (options) {
    return new Cesium.ModelGraphics({
      uri: options.m_url,
      scale: options.m_scale || 28,
      minimumPixelSize: options.m_minimumPixelSize || 30,
      color: options.m_color || Cesium.Color.WHITE
    })
  }
}

function getLabelGraphics(options) {
  if (options && options.l_text) {
    return new Cesium.LabelGraphics({
      text: options.l_text,
      font: options.l_font || '14px sans-serif',
      fillColor: options.l_fillColor || Cesium.Color.GOLD,
      style: options.l_style || Cesium.LabelStyle.FILL_AND_OUTLINE,
      outlineWidth: options.l_outlineWidth || 2,
      outlineColor: options.l_outlineColor || undefined,
      showBackground: options.l_showBackground || false,
      backgroundColor: options.l_backgroundColor || new Cesium.Color(0.165, 0.165, 0.165, 0.8),
      verticalOrigin: options.l_verticalOrigin || Cesium.VerticalOrigin.BOTTOM,
      pixelOffset: options.l_pixelOffset || new Cesium.Cartesian2(0, -30)
      //heightReference:Cesium.HeightReference.RELATIVE_TO_GROUND
    })
  }
}

function getBillboardGraphics(options) {
  if (options && options.b_img) {
    return new Cesium.BillboardGraphics({
      image: options.b_img,
      width: options.b_width || 35,
      height: options.b_height || 35,
      clampToGround: options.b_clampToGround || true,
      scale: options.b_scale || 1,
      // eyeOffset :new Cesium.Cartesian2(0, -20),
      pixelOffset: options.b_pixelOffset || new Cesium.Cartesian2(0, -20),
      scaleByDistance: options.b_scaleByDistance || undefined
      // heightReference:Cesium.HeightReference.RELATIVE_TO_GROUND
    })
  }
}

export default function useCustomEntity(options) {
  if (window.viewer && options && options.paths) {
    const _paths = options.paths
    const _positionProperty = new Cesium.SampledPositionProperty()
    const _rEntity = new Cesium.Entity()
    const _directionProperty = new Cesium.SampledPositionProperty()
    const _startTime = new Cesium.JulianDate()
    let _direction = null
    let _stopTime = null
    let _increment = null
    let _time = null
    if (options.times) {
      let _times = options.times - (options.times % (_paths.length - 1))
      ;(_stopTime = Cesium.JulianDate.addSeconds(_startTime, _times, new Cesium.JulianDate())),
        (_increment = _times / (_paths.length - 1))
    } else {
      _stopTime = Cesium.JulianDate.addSeconds(
        _startTime,
        (_paths.length - 1) * (options.step || 120),
        new Cesium.JulianDate()
      )
    }
    const startTime = options.startTime || _startTime
    const stopTime = options.stopTime || _stopTime
    window.viewer.clock.startTime = startTime.clone()
    window.viewer.clock.currentTime = startTime.clone()
    window.viewer.clock.stopTime = stopTime.clone()
    window.viewer.clock.multiplier = options.multiplier || 10
    window.viewer.clock.clockRange = options.clockRange || Cesium.ClockRange.LOOP_STOP
    for (let i = 0; i < _paths.length; i++) {
      const cartesian = Cesium.Cartesian3.fromDegrees(_paths[i].lon, _paths[i].lat, _paths[i].alt)
      if (options.times) _time = Cesium.JulianDate.addSeconds(startTime, i * _increment, new Cesium.JulianDate())
      else _time = Cesium.JulianDate.addSeconds(startTime, _paths[i].time, new Cesium.JulianDate())
      _positionProperty.addSample(_time, cartesian)
      let directionCartesian = null
      if (i === _paths.length - 1) {
        _directionProperty.addSample(_time, _direction)
        continue
      } else {
        directionCartesian = Cesium.Cartesian3.fromDegrees(_paths[i + 1].lon, _paths[i + 1].lat, _paths[i + 1].alt)
      }
      _direction = getDirection(directionCartesian, cartesian)
      _directionProperty.addSample(_time, _direction)
    }
    _rEntity.name = options.name || '漫游Entity'
    _rEntity.availability = new Cesium.TimeIntervalCollection([
      new Cesium.TimeInterval({ start: startTime, stop: stopTime })
    ])
    _rEntity.position = _positionProperty
    _rEntity.orientation = new Cesium.VelocityOrientationProperty(_positionProperty)
    _rEntity.direction = _directionProperty
    if (options.model) _rEntity.model = getModelGraphics(options)
    if (options.label) _rEntity.label = getLabelGraphics(options)
    if (options.billboard) _rEntity.billboard = getBillboardGraphics(options)
    onMounted(() => window.viewer.entities.add(_rEntity))
    return { _rEntity }
  }
}

3.3、自定义 Cesium 的移动光源的 vue hook 如下:

js 复制代码
import { onMounted } from 'vue'

export default function useCustomLight(position, options) {
  if (window.viewer && position) {
    const DEF_OPTS = {
      color: options.color || new Cesium.Color(1, 1, 2, 0.8),
      cutoffDistance: options.cutoffDistance || 1000,
      decay: options.decay || 0.5,
      intensity: options.intensity || 1
    }
    const _options = options || DEF_OPTS
    const customLight = new Cesium.PointLight(position, _options)
    onMounted(() => window.viewer.scene.addLightSource(customLight))
    return { customLight }
  }
}

3.4、向场景添加飞行无人机 Entity

js 复制代码
const { _rEntity: flyEntity } = useCustomEntity({
  paths: [
    { lon: 116.44596605973072, lat: 39.90275976224633, alt: 400, time: 0 },
    { lon: 116.470769862146, lat: 39.90961660773017, alt: 400, time: 120 },
    { lon: 116.44621270736882, lat: 39.912427615595874, alt: 400, time: 240 },
    { lon: 116.45867843557505, lat: 39.92072065356812, alt: 400, time: 360 },
    { lon: 116.469697344222, lat: 39.91736853889283, alt: 400, time: 480 },
    { lon: 116.46625570699818, lat: 39.91100981903596, alt: 400, time: 600 }
  ],
  model: true,
  m_url: '/model/CesiumDrone.gltf',
  label: true,
  l_text: '无人机一号',
  l_outlineWidth: 3,
  l_fillColor: Cesium.Color.CYAN
})

3.5、向场景添加移动光源

js 复制代码
const { customLight: light } = useCustomLight(flyEntity.position.getValue(viewer.clock.currentTime), {
  color: new Cesium.Color(0, 140, 140, 0.8),
  cutoffDistance: 500,
  decay: 2,
  intensity: 5
})

3.6、设置光源跟随无人机 Entity 移动

js 复制代码
window.viewer.clock.onTick.addEventListener(() => {
  light.position = flyEntity.position.getValue(viewer.clock.currentTime)
})
相关推荐
汪洪墩30 分钟前
【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换
开发语言·javascript·python·ecmascript·webgl·cesium
不浪brown8 小时前
仅需3行代码!带你做一个3D卫星轨道飞行动画
cesium
枝上棉蛮1 天前
免费GIS工具箱:轻松将glb文件转换成3DTiles文件
gis·数字孪生·数据格式转换·3dtiles·地理信息系统·glb·gis软件
白嫖叫上我2 天前
Cesium 无人机航线规划(航点航线)
无人机·cesium
BJ-Giser4 天前
前端解析超图的iserver xml
前端·可视化·cesium
我码玄黄4 天前
在Cesium中加载OD线
前端·javascript·cesium
supermapsupport4 天前
iClient3D for Cesium 实现限高分析
3d·vue·gis·cesium·supermap·webgis
白嫖叫上我5 天前
Cesium 无人机航线规划(区域航线)
无人机·cesium
智方科技9 天前
探索 Cesium 的未来:3D Tiles Next 标准解析
前端·算法·3d·信息可视化·webgl·cesium·tilesbuilder