【CesiumJS-5】绘制动态路线实现飞行航线、汽车轨迹、路径漫游等

实现效果

前言

Cesium中,动态路线绘制的核心是借助CZML格式,CZML是一种用来描述动态场景的JSON数组,可以用来描述点、线、多边形、体、模型及其他图元,同时定义它们是怎样随时间变化的

CZML主要做三件事:

1.添加模型信息

2.添加路径信息

3.计算速度,修改时间

CZML数据格式

[{"id": "document","version": "1.0","clock": {"interval": "2024-03-13T03:00:00Z/2024-03-13T03:12:50Z","currentTime": "2024-03-13T03:00:00Z","multiplier": 5}},{"id": "plane","availability": "2024-03-13T03:00:00Z/2024-03-13T03:12:50Z","viewFrom": {cartesian: [-2080, -1715, 779]},"model": {"gltf": "/model/plane.glb","scale": 2},"orientation": {"velocityReference": "#position"},"path": {"material": {"solidColor": {"color": {"interval": "2024-03-13T03:00:00Z/2024-03-13T03:12:50Z","rgba": [0, 0, 205, 255]}}},"width": [{"interval": "2024-03-13T03:00:00Z/2024-03-13T03:12:50Z","number": 2}],"show": [{"interval": "2024-03-13T03:00:00Z/2024-03-13T03:12:50Z","boolean": true}]},"position": {"interpolationAlgorithm": "LAGRANGE","interpolationDegree": 1,"epoch": "2024-03-13T03:00:00Z","cartographicDegrees": []}}
]

主要有两个对象组成:第一个对象声明czml,第二个对象生成模型。

1. 声明czml
  {"id": "document","version": "1.0","clock": {"interval": "2024-03-13T03:00:00Z/2024-03-13T03:12:50Z","currentTime": "2024-03-13T03:00:00Z","multiplier": 5}}
2. 设置相机位置
    "viewFrom": {cartesian: [-2080, -1715, 779]},
3. 生成场景模型,设置时间范围
  {"id": "plane","availability": "2024-03-13T03:00:00Z/2024-03-13T03:12:50Z","model": {"gltf": "/model/plane.glb","scale": 2}}
4. 设置模型运动方向
    "orientation": {"velocityReference": "#position"},
5. 生成动态路径
    "path": {"material": {"solidColor": {"color": {"interval": "2024-03-13T03:00:00Z/2024-03-13T03:12:50Z","rgba": [0,0,205,255]}}},"width": [{"interval": "2024-03-13T03:00:00Z/2024-03-13T03:12:50Z","number": 2}],"show": [{"interval": "2024-03-13T03:00:00Z/2024-03-13T03:12:50Z","boolean": true}]},
6. 设置运动路线

cartographicDegrees设置经纬度:4个一组分别是 时间,经度,纬度,高度

    "position": {"interpolationAlgorithm": "LAGRANGE","interpolationDegree": 1,"epoch": "2024-03-13T03:00:00Z","cartographicDegrees": [0, 120.13125463180745, 30.316189813141357, 20]}

功能实现

本人在实现功能中没用json格式,而是直接用的数组对象变量,上述中仅做学习记录。

注意: czml只能识别ISO8601日期,需要使用Cesium内置方法转换时间;

1. 将当前时间作为开始时间并将js日期转为儒略日格式
const start = Cesium.JulianDate.fromDate(new Date());
2. 创建czml数组

使用Cesium.JulianDate.toIso8601()方法将时间转为ISO8601日期格式

const czml = [{id: "document",version: "1.0",clock: {interval: `${Cesium.JulianDate.toIso8601(start, 0)}/${Cesium.JulianDate.toIso8601(Cesium.JulianDate.addSeconds(start, 450, new Cesium.JulianDate()), 0)}`,currentTime: `${Cesium.JulianDate.toIso8601(start, 0)}`,multiplier: 10,}},{id: "plane",availability: `${Cesium.JulianDate.toIso8601(start, 0)}/${Cesium.JulianDate.toIso8601(Cesium.JulianDate.addSeconds(start, 450, new Cesium.JulianDate()), 0)}`,model: {gltf: "/model/plane.glb",scale: 2},// viewFrom: {//   cartesian: [-2080, -1715, 779]// },orientation: {velocityReference: "#position"},path: {material: {solidColor: {color: {interval: `${Cesium.JulianDate.toIso8601(start, 0)}/${Cesium.JulianDate.toIso8601(Cesium.JulianDate.addSeconds(start, 450, new Cesium.JulianDate()), 0)}`,rgba: [0, 0, 205, 255]}}},width: [{interval: `${Cesium.JulianDate.toIso8601(start, 0)}/${Cesium.JulianDate.toIso8601(Cesium.JulianDate.addSeconds(start, 450, new Cesium.JulianDate()), 0)}`,number: 2}],show: [{interval: `${Cesium.JulianDate.toIso8601(start, 0)}/${Cesium.JulianDate.toIso8601(Cesium.JulianDate.addSeconds(start, 450, new Cesium.JulianDate()), 0)}`,boolean: true}]},position: {interpolationAlgorithm: "LAGRANGE",interpolationDegree: 1,epoch: `${Cesium.JulianDate.toIso8601(start, 0)}`,cartographicDegrees: [0, 120.13125463180745, 30.316189813141357, 5,10, 120.13111416662538, 30.315539106519307, 5,20, 120.1309786622693, 30.31489588182787, 5,30, 120.13084876734133, 30.314235695359727, 5,40, 120.13069473575192, 30.313540629197277, 5,50, 120.13054390032266, 30.312912654513724, 5,60, 120.13044947371688, 30.312385482730374, 5,70, 120.13030971147948, 30.311910736974383, 5,80, 120.13009317468772, 30.311390245082837, 5,90, 120.12978893985873, 30.310733495046055, 5,100, 120.12959024998796, 30.310326531696383, 10,110, 120.12938465577722, 30.309954975972268, 30,120, 120.12903852757415, 30.309336955328902, 60,130, 120.12871206396551, 30.308875801472478, 70,140, 120.12838069578686, 30.308490868344943, 70,150, 120.12810457466928, 30.308113523536672, 70,160, 120.12779772791689, 30.307774086249907, 80,170, 120.12737964279644, 30.307483823729378, 80,180, 120.1269732925855, 30.307160879171903, 80,190, 120.12647213239983, 30.30666310390423, 80,200, 120.12546262988464, 30.307181930544864, 80,210, 120.1245785033241, 30.307683795316315, 80,220, 120.12375576753382, 30.308035432883194, 100,230, 120.12308850447974, 30.308497699718018, 100,240, 120.12253685192415, 30.308860660895174, 100,250, 120.12209783635902, 30.309214249085528, 100,260, 120.12124539807733, 30.309730900111948, 120,270, 120.12062513785223, 30.30968143768237, 125,280, 120.11996146408914, 30.30903962813221, 130,290, 120.12080592297113, 30.308199027265523, 135,300, 120.1206419712799, 30.307743185311676, 140,310, 120.11991139765998, 30.306939478614392, 200,320, 120.11894945108537, 30.307236007284757, 220,330, 120.11843736124806, 30.307682602103153, 240,340, 120.11801295026378, 30.308682424137178, 260,350, 120.117608250043, 30.30896814314354, 280,360, 120.11756912872843, 30.309470200064347, 300,370, 120.11718042273918, 30.310442342271475, 300,380, 120.11602779574089, 30.3098989524904, 310,390, 120.11550616761767, 30.31093863353403, 310,400, 120.11644406776917, 30.31177509905328, 310,410, 120.11566744726449, 30.312255943277282, 320,420, 120.11627775321915, 30.312631949114188, 320,430, 120.11695495518998, 30.313251980473588, 330,440, 120.11755845523233, 30.313636377593916, 330,450, 120.11843011762987, 30.31389033163698, 340]}}
]
3. 加载CZML数据并添加到场景中

dataSources:是一个异步Promise,回调参数为我们传入的czml数据;

let dataSource = viewer.dataSources.add(Cesium.CzmlDataSource.load(czml));
4. 相机跟随模型
  dataSource.then(part => {// 根据id获取czml中的模型let e = part.entities.getById("plane");// 相机跟随模型viewer.trackedEntity = e;});
5. 视角跟随模型
  dataSource.then(part => {// 根据id获取czml中的模型let e = part.entities.getById("plane");// 相机跟随模型viewer.trackedEntity = e;//++++++++++++++// 视角跟随模型let prePoint = null; // 前一个点viewer.scene.postRender.addEventListener(() => {if (e && viewer.clock.shouldAnimate) {// 获取当前时间的位置let curPoint = e.position.getValue(viewer.clock.currentTime);if (prePoint) {// 计算heading-代表 Z 轴旋转let heading = getHeading(prePoint, curPoint);// 计算pitch-代表 Y 轴朝向let pitch = Cesium.Math.toRadians(-30.0);let range = 100;viewer.camera.lookAt(curPoint, new Cesium.HeadingPitchRange(heading, pitch, range));}// 当前点在下一次渲染时为前一个点prePoint = Cesium.Cartesian3.clone(curPoint)}}) });function getHeading(pointA, pointB) {//建立以点A为原点,X轴为east,Y轴为north,Z轴朝上的坐标系const transform = Cesium.Transforms.eastNorthUpToFixedFrame(pointA);//向量ABconst positionvector = Cesium.Cartesian3.subtract(pointB, pointA, new Cesium.Cartesian3());//因transform是将A为原点的eastNorthUp坐标系中的点转换到世界坐标系的矩阵//AB为世界坐标中的向量//因此将AB向量转换为A原点坐标系中的向量,需乘以transform的逆矩阵。const vector = Cesium.Matrix4.multiplyByPointAsVector(Cesium.Matrix4.inverse(transform, new Cesium.Matrix4()), positionvector, new Cesium.Cartesian3());//归一化const direction = Cesium.Cartesian3.normalize(vector, new Cesium.Cartesian3());//headingconst heading = Math.atan2(direction.y, direction.x) - Cesium.Math.PI_OVER_TWO;return Cesium.Math.TWO_PI - Cesium.Math.zeroToTwoPi(heading);
}

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

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

相关文章

如何在Linux系统部署APITable容器并实现无公网IP远程管理本地数据

文章目录 前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 前言 vika维格表作为新一代数据生产力平台,是一款面向 API 的智能多维表格。它将复杂的可视化数据库、电子表格、实时在线协同、低代码开发技术四合为一&am…

C#,蛇梯问题(Snake and Ladder Problem)的算法与源代码

1 蛇梯问题 Snake and Ladder Problem 给定一个蛇梯板,找出从源单元格或第一个单元格到达目标单元格或最后一个单元格所需的最小掷骰次数。基本上,玩家可以完全控制掷骰子的结果,并希望找出到达最后一个单元格所需的最小掷骰次数。 如果玩家到达的牢房是梯子的底部,玩家…

(PTA乙级)1045 快速排序 (单调栈思想)

著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的 N 个互不相同的正整数的排列,请问有多少个元…

Java 调用 Groovy 脚本的简单案例

Java 调用 Groovy 脚本的简单案例 前言 Groovy 和 Java 都是使用 JVM 虚拟机进行解释执行的。工作中会遇到一些场景,需要对特殊的业务进行解耦。那段业务可能会经常变动,如果直接在Java代码里写业务的话就会涉及频繁的发包服务重启这类情况,…

金融防线升级:构筑数据安全的不可逾越之墙

近日,中国人民银行专栏《金融科技支持高质量发展》指出,应不断增强金融行业的网络安全和数据安全保障能力,坚持总体国家安全观,持续完善金融网络安全、数据安全制度体系,依法开展金融业关键信息基础设施安全保护工作&a…

mac删除带锁标识的app

一 、我们这里要删除FortiClient.app 带锁 常规方式删除不掉带锁的 app【如下图】 二、删除命令,依次执行即可。 /bin/ls -dleO /Applications/FortiClient.app sudo /usr/bin/chflags -R noschg /Applications/FortiClient.app /bin/ls -dleO /Applications/Forti…

Wireshark4.2.3 x64 Setup20240313

参考:【抓包工具】win 10 / win 11:WireShark 下载、安装、使用(https://blog.csdn.net/qq_39720249/article/details/128157223) 文章目录 下载安装12 license 许可证3 donations:捐款4 Choose Components&#xff1…

算法-图的存储,图的转置,拓扑排序

1.图的存储 图用来对关系建模.图是节点和边构成的集合.节点反映图的元素集合,边反映图的元素集合中元素间的关系. 上述是由五个节点,三条边构成的结构.我们可以用图对其建模. 对由节点&#x…

大数据开发(Kafka面试真题-卷三)

大数据开发(Kafka面试真题) 1、Kafka是如何进行数据备份的?2、Kafka里面存的数据格式是什么样的?3、Kafka是如何清理过期文件的?4、Kafka的一条message中包含了哪些信息?5、Kafka中的数据能彻底删除吗&…

【Python】Leetcode 240. 搜索二维矩阵 II - 削减矩阵+递归,击败88%

描述 搜索二维矩阵 II 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。 该矩阵具有以下特性: 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 思路 确定左右及上下限,削减矩阵,递归。 注意判断四个端…

Python 面向对象

在 Python 中,面向对象编程(Object-Oriented Programming,OOP)是一种程序设计范例,它以对象为基础,将数据和操作封装在对象内部,通过定义类和创建对象来实现。让我们来介绍 Python 中面向对象编…

【Git】统计所有仓库单个用户的代码提交量

将以下代码保存为 gitStatics.sh,并且放置在存放所有仓库的文件夹内,与仓库文件保持同级。 #!/bin/bash # 检查是否提供了足够的参数 if [ "$#" -ne 1 ]; then echo "Usage: $0 <username>" exit 1 fi # 获取用户名参数 user

API数据能力开放架构 数据api接口

一.API数据接口可以从几个不同的角度来看待&#xff1a; 1. 技术角度&#xff1a;API数据接口是一种技术实现&#xff0c;通常是以HTTP协议或其他网络协议为基础&#xff0c;并采用特定的数据格式&#xff08;如JSON或XML&#xff09;来传递数据。 2. 业务角度&#xff1a;API…

视口坐标转换成Canvas下本地坐标与shader显示在3D物体前

shader显示在3D物体前&#xff0c;先转化成视口坐标 public virtual void SetESignPos() { float x 0; float y 0; int v PlayerPrefsTool.GetSpecialScreen(-1); if (EScreenCamera ! null) { Vector3 viewPointEScreenCa…

前端input上传文件 使用new FormData()同时上传文件类型和JSON数据

失败案例 async uploadFileHandler(e) {if (e.target.files.length) {const files e.target.files[0];let formData new FormData();formData.append("file", files);formData.append("module", "knowledge");fileupload(formData).then(res …

JVM探究

JVM探究 请你谈谈你对JVM的理解&#xff1f;java -> class -> jvm java 8虚拟机和之前的变化更新OOM 内存溢出。栈溢出 StackOverFlowError > 怎么分析JVM的常用调优参数 &#xff1f; 扩大内存内存快照如何抓取&#xff0c;怎么分析Dump文件&#xff1f;知道吗&…

SAP 生产订单中计划成本问题简介

最近财务在月结的时候,发现有生产订单结算的时候有物料不存在计划成本,并且财务顾问反馈这个问题已经存在有一段时间了。通过对生产订单的成本分析按钮查看生产订单的成本 发现确实存在有物料不存在计划成本,但是生产订单存在实际成本。 1、首先想到的是无计划成本的原材料…

使用Python进行图片格式转化/分辨率转化

一.下载python PIY插件库 PIP下载命令: pip install pillow -i https://mirrors.aliyun.com/pypi/simple PIY插件库:pillow Installation - Pillow (PIL Fork) 10.3.0.dev0 documentation 二.分辨率转化 from PIL import Image import osresolution (1024, 1024) with Image…

redis监控

一、Redis监控方法 1、redis info命令 Redis的监控指标主要通过INFO命令获取&#xff0c;该命令可以返回丰富的运行监控信息。info主要有以下几项&#xff0c;因版本不同可能略有差别&#xff1a; # Server redis_version:7.2.4 redis_git_sha1:00000000 redis_git_dirty:0 …

C语言易错知识点:scanf函数

scanf在C语言学习中比较常用&#xff0c;但因为其涉及屏幕缓冲区导致有的时候会调入陷阱&#xff0c;下面分享一下常见的需要注意的事项&#xff1a; 1.输入末尾带有回车\n 当我们输入数据后&#xff0c;最后按下回车时&#xff0c;屏幕缓冲区的末尾都会含有这个字符 scanf的…