Cesium实战三:飞行航线动画

news2024/11/18 17:48:12

飞行航线追踪

可视化从旧金山到哥本哈根的真实航班。

1、获取点位数据:构建飞行跟踪器 – Cesium (cesium.com)

2、在地图上添加飞行点位:循环遍历点位数据,利用Entity直接添加点至地图上。

//添加飞行点位
const addFlightPoint = () => {
  const length = filghtData.length;
  for (let i = 0; i < length; i++) {
    const dataPoint = filghtData[i];
    viewer.entities.add({
      description: `Location:(${dataPoint.longitude},${dataPoint.latitude},${dataPoint.height})`,
      position: Cesium.Cartesian3.fromDegrees(
        dataPoint.longitude, //经度
        dataPoint.latitude, //纬度
        dataPoint.height //高度
      ),
      point: {
        pixelSize: 8, //点尺寸
        color: Cesium.Color.RED, //点颜色
      },
    });
  }
};

3、将飞行点位连接起来,并创建飞行移动实体:

  • 假设雷达样本采样间隔为30s,设定飞行开始时间,飞行结束时间由飞行开始时间+飞行持续时间计算出来。
  • 将开始、结束时间绑定到viewer的时间轴上去,调整时间速率,开启时间动画。
  • 利用采样位置属性实例Cesium.SampledPositionProperty(),循环遍历将所有点与时间创建成样本实例并利用addSample()添加进采样位置属性实例。
  • 创建飞机模型实例,绑定时间间隔集合。利用 Cesium.VelocityOrientationProperty()将飞机实体方向设置为样本一致。
  • 创建飞行路线,利用Cesium.PathGraphics({ width: 3 })设置线条宽度为3.
  • 利用 viewer.trackedEntity = airPlaneEntity设置相机视角跟随飞机实体。
//将飞行点位连接起来,并创建飞行移动实体
const createFlyLine = () => {
  const length = filghtData.length;
  const timeStepInSeconds = 30; //雷达样本间隔
  const totalSeconds = timeStepInSeconds * (length - 1); //飞行的持续时间
  const start = Cesium.JulianDate.fromIso8601("2022-12-17T23:10:00Z"); //飞行开始时间
  const stop = Cesium.JulianDate.addSeconds(
    start,
    totalSeconds,
    new Cesium.JulianDate()
  ); //通过计算获得飞行结束时间

  viewer.clock.startTime = start; //开始时间
  viewer.clock.stopTime = stop; //停止时间
  viewer.clock.currentTime = start; //当前时间
  viewer.timeline.zoomTo(start, stop); //将视图设置为提供的时间。

  viewer.clock.multiplier = 50; //加快播放速度
  viewer.clock.shouldAnimate = true; //时针向前走
  //创建采样位置属性实例
  const positionProperty = new Cesium.SampledPositionProperty();
  for (let i = 0; i < length; i++) {
    const dataPoint = filghtData[i];
    const time = Cesium.JulianDate.addSeconds(
      start,
      i * timeStepInSeconds,
      new Cesium.JulianDate()
    );
    const position = Cesium.Cartesian3.fromDegrees(
      dataPoint.longitude,
      dataPoint.latitude,
      dataPoint.height
    );
    positionProperty.addSample(time, position); //调用addSample方法将样本实例添加进去
  }
  //添加飞机模型
  // const airPlaneUri = Cesium.IonResource.fromAssetId(1980066).then((a)=>{return a});
  // console.log(airPlaneUri);

  const airPlaneEntity = viewer.entities.add({
    //创建时间间隔集合
    availability: new Cesium.TimeIntervalCollection([
      new Cesium.TimeInterval({ start: start, stop: stop }), //创建时间间隔
    ]),
    position: positionProperty,
    //添加飞机模型
    model: {
      uri: "../public/GLB/Cesium_Air.glb",
      minimumPixelSize: 128,
      maximumScale: 20000,
    },
    orientation: new Cesium.VelocityOrientationProperty(positionProperty), //设置方向与采样属性一致
    path: new Cesium.PathGraphics({ width: 3 }), //路径图形,并宽度为3
  });
  viewer.trackedEntity = airPlaneEntity; //视角跟随飞机实体
};

4、添加三维建筑、地形图层:

//添加三维建筑
const loadOSMBuildings = async () => {
  viewer.scene.primitives.add(
    await Cesium.Cesium3DTileset.fromIonAssetId(96188, {
      show: true,
    })
  );
};
//添加地形
const addTerrainProvider = async () => {
  viewer.terrainProvider =
    await Cesium.ArcGISTiledElevationTerrainProvider.fromUrl(
      "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer",
      {
        token:
          "KED1aF_I4UzXOHy3BnhwyBHU4l5oY6rO6walkmHoYqGp4XyIWUd5YZUC1ZrLAzvV40pR6gBXQayh0eFA8m6vPg..",
      }
    );
};

在这里插入图片描述

附:完整代码:

<template>
  <div id="view_container"></div>
</template>
<script setup lang="ts">
import * as Cesium from "cesium";
import "../public/Widgets/widgets.css";
import { onMounted } from "vue";

import filghtData from "../public/JSON/flightData.json";

let viewer: Cesium.Viewer; //地图实例

//中国地图JSON:https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json
//1、加载静态资源
window.CESIUM_BASE_URL = "/";
//2、添加令牌
Cesium.Ion.defaultAccessToken ="your token"
//3、设置地图初始默认视角
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
  73.5, //西经
  4, //南纬
  135.4, //东经
  53.5 //北纬
);
onMounted(async () => {
  //5、创建并初始化viewer实例
  viewer = new Cesium.Viewer("view_container", {
    infoBox: false, //小弹窗
    // animation: false, //左下角动画仪表盘
    baseLayerPicker: false, //右上角图层选择按钮
    geocoder: false, //搜索框
    homeButton: false, //home按钮
    sceneModePicker: false, //模式切换按钮
    // timeline: false, //底部时间轴
    navigationHelpButton: false, //右上角帮助按钮
    fullscreenButton: false, //右下角全屏按钮
    selectionIndicator: false, //选择指示器
  });
  //6、隐藏logo
  (viewer.cesiumWidget.creditContainer as HTMLElement).style.display = "none";
  loadGeoJSON();
  loadCZML();
  addFlightPoint();
  createFlyLine();
  loadOSMBuildings();
  addTerrainProvider();
});

//7、加载GeoJSON数据
const loadGeoJSON = () => {
  // viewer.dataSources.add(Cesium.GeoJsonDataSource.load('https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json',{
  //   stroke:Cesium.Color.fromCssColorString('#048dfa'),//折线和多边形轮廓的默认颜色。
  //   fill:Cesium.Color.fromCssColorString('#afd6f0'),//填充颜色#048dfa
  //   strokeWidth:3,//轮廓宽度
  //   markerSymbol:'?',//为每个点创建的地图图钉的默认符号。
  // }));
  //因为加载是Ajax请求,所以可以使用以下方式加载
  Cesium.GeoJsonDataSource.load(
    "https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json",
    {
      stroke: Cesium.Color.fromCssColorString("#048dfa"), //折线和多边形轮廓的默认颜色。
      fill: Cesium.Color.fromCssColorString("#afd6f0"), //填充颜色#048dfa
      strokeWidth: 3, //轮廓宽度
      markerSymbol: "?", //为每个点创建的地图图钉的默认符号。
    }
  ).then((dataSources: Cesium.GeoJsonDataSource) => {
    viewer.dataSources.add(dataSources);
  });
};

//8、加载KML
//9、加载czml
const czml = [
  {
    id: "document",
    name: "box",
    version: "1.0",
  },
  {
    id: "shape1",
    name: "Blue box",
    position: {
      cartographicDegrees: [-114.0, 40.0, 300000.0],
    },
    box: {
      dimensions: {
        cartesian: [400000.0, 300000.0, 500000.0],
      },
      material: {
        solidColor: {
          color: {
            rgba: [0, 0, 255, 255],
          },
        },
      },
    },
  },
  {
    id: "shape2",
    name: "Red box with black outline",
    position: {
      cartographicDegrees: [-107.0, 40.0, 300000.0],
    },
    box: {
      dimensions: {
        cartesian: [400000.0, 300000.0, 500000.0],
      },
      material: {
        solidColor: {
          color: {
            rgba: [255, 0, 0, 128],
          },
        },
      },
      outline: true,
      outlineColor: {
        rgba: [0, 0, 0, 255],
      },
    },
  },
  {
    id: "shape3",
    name: "Yellow box outline",
    position: {
      cartographicDegrees: [-100.0, 40.0, 300000.0],
    },
    box: {
      dimensions: {
        cartesian: [400000.0, 300000.0, 500000.0],
      },
      fill: false,
      outline: true,
      outlineColor: {
        rgba: [255, 255, 0, 255],
      },
    },
  },
];
const loadCZML = () => {
  Cesium.CzmlDataSource.load(czml).then(
    (datasoutcePromise: Cesium.CzmlDataSource) => {
      viewer.dataSources.add(datasoutcePromise);
    }
  );
};
//10、添加飞行点位
const addFlightPoint = () => {
  const length = filghtData.length;
  for (let i = 0; i < length; i++) {
    const dataPoint = filghtData[i];
    viewer.entities.add({
      description: `Location:(${dataPoint.longitude},${dataPoint.latitude},${dataPoint.height})`,
      position: Cesium.Cartesian3.fromDegrees(
        dataPoint.longitude, //经度
        dataPoint.latitude, //纬度
        dataPoint.height //高度
      ),
      point: {
        pixelSize: 8, //点尺寸
        color: Cesium.Color.RED, //点颜色
      },
    });
  }
};
//11、将飞行点位连接起来,并创建飞行移动实体
const createFlyLine = () => {
  const length = filghtData.length;
  const timeStepInSeconds = 30; //雷达样本间隔
  const totalSeconds = timeStepInSeconds * (length - 1); //飞行的持续时间
  const start = Cesium.JulianDate.fromIso8601("2022-12-17T23:10:00Z"); //飞行开始时间
  const stop = Cesium.JulianDate.addSeconds(
    start,
    totalSeconds,
    new Cesium.JulianDate()
  ); //通过计算获得飞行结束时间

  viewer.clock.startTime = start; //开始时间
  viewer.clock.stopTime = stop; //停止时间
  viewer.clock.currentTime = start; //当前时间
  viewer.timeline.zoomTo(start, stop); //将视图设置为提供的时间。

  viewer.clock.multiplier = 50; //加快播放速度
  viewer.clock.shouldAnimate = true; //时针向前走
  //创建采样位置属性实例
  const positionProperty = new Cesium.SampledPositionProperty();
  for (let i = 0; i < length; i++) {
    const dataPoint = filghtData[i];
    const time = Cesium.JulianDate.addSeconds(
      start,
      i * timeStepInSeconds,
      new Cesium.JulianDate()
    );
    const position = Cesium.Cartesian3.fromDegrees(
      dataPoint.longitude,
      dataPoint.latitude,
      dataPoint.height
    );
    positionProperty.addSample(time, position); //调用addSample方法将样本实例添加进去
  }
  //添加飞机模型
  // const airPlaneUri = Cesium.IonResource.fromAssetId(1980066).then((a)=>{return a});
  // console.log(airPlaneUri);

  const airPlaneEntity = viewer.entities.add({
    //创建时间间隔集合
    availability: new Cesium.TimeIntervalCollection([
      new Cesium.TimeInterval({ start: start, stop: stop }), //创建时间间隔
    ]),
    position: positionProperty,
    //添加飞机模型
    model: {
      uri: "../public/GLB/Cesium_Air.glb",
      minimumPixelSize: 128,
      maximumScale: 20000,
    },
    orientation: new Cesium.VelocityOrientationProperty(positionProperty), //设置方向与采样属性一致
    path: new Cesium.PathGraphics({ width: 3 }), //路径图形,并宽度为3
  });
  viewer.trackedEntity = airPlaneEntity; //视角跟随飞机实体
};
//12、添加三维建筑
const loadOSMBuildings = async () => {
  viewer.scene.primitives.add(
    await Cesium.Cesium3DTileset.fromIonAssetId(96188, {
      show: true,
    })
  );
};
//13、添加地形
const addTerrainProvider = async () => {
  viewer.terrainProvider =
    await Cesium.ArcGISTiledElevationTerrainProvider.fromUrl(
      "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer",
      {
        token:
          "KED1aF_I4UzXOHy3BnhwyBHU4l5oY6rO6walkmHoYqGp4XyIWUd5YZUC1ZrLAzvV40pR6gBXQayh0eFA8m6vPg..",
      }
    );
};
</script>
<style>
html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
*,
#app {
  margin: 0;
  padding: 0;
}
#view_container {
  width: 100vw;
  height: 100vh;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1492246.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络(2)-----数据链路层

目录 一.数据链路层的基本概念 二.数据链路层的功能概述 功能一:为网络层提供服务。无确认无连接服务&#xff0c;有确认无连接服务&#xff0c;有确认面向连接服务。 功能二:链路管理&#xff0c;即连接的建立、维持、释放(用于面向连接的服务)。 功能三:组帧 透明传输:…

基于Django的携程网Top热门景点数据可视化分析

前言&#xff1a; 今天给大家分享一个基于Django的携程网Top热门景点数据可视化分析项目&#xff0c;以下是该项目大大概内容 项目名称&#xff1a;基于Python&#xff08;django&#xff09;的携程Top热门景点数据可视化分析 涉及技术&#xff1a;Python&#xff0c;Djang…

为什么有了HTTP协议,还要有WebSocket协议?

文章目录 使HTTP不断轮询长轮询WebSocket是什么&#xff1f;怎么建立WebSocket连接WebSocket抓包WebSocket的消息格式WebSocket的使用场景总结 平时我们打开网页&#xff0c;比如购物网站某宝。都是点一下列表商品&#xff0c;跳转一下网页就到了商品详情。 从HTTP协议的角度来…

[C语言]——scanf和printf介绍

目录 一.printf 1.基本用法 2.占位符 3.占位符列举 4.输出格式 4.1限定宽度 4.2总是显示正负号 4.3限定小数位数 4.4输出部分字符串 二.scanf 1.基本用法 2.scanf的返回值 3.占位符 4.赋值忽略符 一.printf 1.基本用法 printf() 的作⽤是将参数⽂本输出到屏幕。…

winui开发笔记(五)应用程序图标

应用程序图标、发布者、显示名称大部分都在package.appxmanifest清单文件中&#xff0c;可以正常打开&#xff0c;也可以使用xml文本编辑器打开。 以下是一个正常的应用程序中所有的与图标相关的图片&#xff1a; 但是设置之后会有一圈白&#xff0c;包括在电脑最下边一行&…

chrome插件extensions获取所有窗口tab页和windows页

获取windows页&#xff1a;https://developer.chrome.com/docs/extensions/reference/api/windows?hlzh-cn 获取所有tabs页&#xff1a;https://developer.chrome.com/docs/extensions/reference/api/tabs?hlzh-cnchrome.tabshttps://developer.chrome.com/docs/extensions/…

MYSQL C++链接接口编程

使用MYSQL 提供的C接口来访问数据库,官网比较零碎,又不想全部精读一下,百度CSDN都是乱七八糟的,大部分不可用 官网教程地址 https://dev.mysql.com/doc/connector-cpp/1.1/en/connector-cpp-examples-connecting.html 网上之所以乱七八糟,主要是MYSQL提供了3个接口两个包,使用…

打家劫舍(java版)

&#x1f4d1;前言 本文主要是【动态规划】——打家劫舍(java版)的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一…

QT对象树 | 内存泄漏

使用 Qt 框架构建 GUI 界面的程序 //widget.cpp #include "widget.h" #include "ui_widget.h" #include <QLabel>Widget::Widget(QWidget *parent) //这里的parent的意思是父级指针: QWidget(parent) //调用父类的构造函数, ui(new Ui::Widget) …

外包干了3个月,技术倒退明显

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

主备DNS服务器搭建并验证

目录 1. 配置静态网络 2. 配置主备DNS 2.1 DNS备服务器&#xff08;第二个虚拟机&#xff09; 2.2 两个虚拟机操作 2.3 备用服务器&#xff08;第二个虚拟机&#xff09;执行 2.4 两个虚拟机都添加DNS: 3. 验证 3.1 主DNS服务验证: 3.2 备用DNS服务器验证&am…

基于Springboot的足球俱乐部管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的足球俱乐部管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍: 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff…

C语言指针的初步认识--学习笔记(3)

1. 字符指针变量 在C语言中&#xff0c;字符串通常被视为字符数组&#xff0c;但它们可以有不同的表示方式。字符指针变量存储的是字符串的地址。这意味着&#xff0c;当你有一个字符串时&#xff0c;你可以通过改变字符指针的值来改变这个字符串&#xff0c;因为你实际上改变的…

22.欧拉方法、刚体模拟、流体模拟

一、一个粒子的模拟 规定一个物体在某一个时刻的速度和位置&#xff0c;如何解出某个时间之后它会出现在哪里 下图要求模拟一个粒子在速度场中要如何运动 速度场中&#xff0c;在任何一个位置&#xff0c;我们都有它的速度 写出来相当于是常微分方程 我们知道速度&#xff0c;…

find函数-秒了道题

秒了 笑死 还是规规矩矩做吧 string类的find()函数用于在字符串中查找字符或子串&#xff0c;返回第一个匹配的位置。 class Solution { public:int strStr(string haystack, string needle) {return haystack.find(needle);} };

基于灰狼算法GWO的城市三维无人机路径规划(复杂地形三维航迹路径规划)

摘要 本文提出了一种利用灰狼算法GWO来解决城市环境下无人机三维路径规划问题的方法。这种方法将复杂的无人机航迹规划任务转化为一个优化问题&#xff0c;然后运用灰狼算法GWO来解决这个优化问题。灰狼算法GWO是一种模拟灰狼种群捕猎行为的优化算法&#xff0c;它具备强大的全…

【TEE】内存完整性保护

Hash Functions&Merkle Tree 对读操作进行完整性检查&#xff0c;通过在加载的块上重新计算一个哈希&#xff0c;然后根据片外地址将得到的哈希与片上哈希比较。 缺点&#xff1a;不可承受的片上存储开销&#xff0c;并假设128位哈希和512位cache line&#xff0c;其开销为…

C++基于多设计模式下的同步异步日志系统day6

C基于多设计模式下的同步&异步日志系统day6 &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C基于多设计模式下的同步&异步日志系统 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&am…

JPA generator 生成实体类

1、配置生成实体类 选中表后点击右键 2、 Generate POJOs.groovy 配置 import com.intellij.database.model.DasTable import com.intellij.database.model.ObjectKind import com.intellij.database.util.Case import com.intellij.database.util.DasUtilimport java.text.S…

K次取反后最大化的数组和 加油站 分发糖果 柠檬水找零

1005.K次取反后最大化的数组和 力扣题目链接(opens new window) 给定一个整数数组 A&#xff0c;我们只能用以下方法修改该数组&#xff1a;我们选择某个索引 i 并将 A[i] 替换为 -A[i]&#xff0c;然后总共重复这个过程 K 次。&#xff08;我们可以多次选择同一个索引 i。&a…