Cesium使用glb模型、图片标记来实现实时轨迹

news2025/6/7 12:43:30

目录

1、使用glb模型进行实时轨迹 

2、使用图片进行实时轨迹 


基于上一篇加载基础地图的代码上继续开发

vue中加载Cesium地图(天地图、高德地图)-CSDN博客文章浏览阅读164次。vue中加载Cesium三维地球 https://blog.csdn.net/ssy001128/article/details/148474799继续在cesium.js中加入需要实现的功能函数方法

 经纬度数据

let interval = null
let coordinateData = [
  {
    lon: 110,
    lat: 30,
    id: "0",
    name: "traject0",
  },
  {
    lon: 110.2,
    lat: 30,
    id: "1",
    name: "traject1",
  },
  {
    lon: 110.4,
    lat: 30.2,
    id: "2",
    name: "traject2",
  },
  {
    lon: 110.8,
    lat: 30.4,
    id: "3",
    name: "traject3",
  },
  {
    lon: 111,
    lat: 31,
    id: "4",
    name: "traject4",
  },
  {
    lon: 111.3,
    lat: 31,
    id: "5",
    name: "traject5",
  },
  {
    lon: 111.6,
    lat: 31,
    id: "6",
    name: "traject6",
  },
  {
    lon: 111.9,
    lat: 31,
    id: "7",
    name: "traject7",
  },
  {
    lon: 112,
    lat: 31,
    id: "8",
    name: "traject8",
  },
  {
    lon: 112.3,
    lat: 31,
    id: "9",
    name: "traject9",
  },
  {
    lon: 112.5,
    lat: 31,
    id: "10",
    name: "traject10",
  },
  {
    lon: 112.8,
    lat: 31,
    id: "11",
    name: "traject11",
  },
  {
    lon: 113,
    lat: 31,
    id: "12",
    name: "traject12",
  },
  {
    lon: 114,
    lat: 31,
    id: "13",
    name: "traject13",
  },
  {
    lon: 115.3,
    lat: 32,
    id: "14",
    name: "traject14",
  },
  {
    lon: 115.5,
    lat: 32,
    id: "15",
    name: "traject15",
  },
  {
    lon: 115.8,
    lat: 31.8,
    id: "16",
    name: "traject16",
  },
  {
    lon: 116,
    lat: 31.4,
    id: "17",
    name: "traject17",
  },
  {
    lon: 116.2,
    lat: 31.1,
    id: "18",
    name: "traject18",
  },
  {
    lon: 116.5,
    lat: 30.5,
    id: "19",
    name: "traject19",
  },
  {
    lon: 115,
    lat: 30.2,
    id: "20",
    name: "traject20",
  },
  {
    lon: 114,
    lat: 29.8,
    id: "21",
    name: "traject21",
  },
  {
    lon: 113,
    lat: 29.6,
    id: "22",
    name: "traject22",
  },
  {
    lon: 112,
    lat: 29.4,
    id: "23",
    name: "traject23",
  },
  {
    lon: 111,
    lat: 30.5,
    id: "24",
    name: "traject24",
  },
  {
    lon: 110,
    lat: 30.4,
    id: "25",
    name: "traject25",
  },
  {
    lon: 109,
    lat: 30.6,
    id: "26",
    name: "traject26",
  },
  {
    lon: 108,
    lat: 36,
    id: "27",
    name: "traject27",
  },
];

1、使用glb模型进行实时轨迹 

模型每次位置改变的朝向可能没有那么标准角度

// 添加使用glb模型进行实时轨迹
export function addGlbTrajectory() {
  // 先添加初始线条
  let arr = [coordinateData[0].lon, coordinateData[0].lat];
  let glbEntity = viewer.entities.add({
    name: "GLB模型示例",
    position: Cesium.Cartesian3.fromDegrees(
      coordinateData[0].lon,
      coordinateData[0].lat
    ),
    // 设置模型初始朝向(这里设置为朝北,即heading=0)
    orientation: Cesium.Transforms.headingPitchRollQuaternion(
      Cesium.Cartesian3.fromDegrees(
        coordinateData[0].lon,
        coordinateData[0].lat
      ),
      new Cesium.HeadingPitchRoll(
        Cesium.Math.toRadians(270), // 朝向(heading):0表示朝北,正数为顺时针旋转(东:90,南:180,西:270)
        0, // 俯仰角(pitch):0表示水平
        0 // 横滚角(roll):0表示不倾斜
      )
    ),
    model: {
      uri: "car.glb",
      scale: 2.0,
      minimumPixelSize: 1228,
      maximumScale: 20000,
      incrementallyLoadTextures: true,
      clampAnimations: true,
      shadows: Cesium.ShadowMode.ENABLED,
    },
  });
  // viewer.trackedEntity = glbEntity;
  let i = 0;
  interval = setInterval(() => {
    // 当数组下标还有数据时
    if (coordinateData[i + 1]) {
      arr.push(coordinateData[i + 1].lon, coordinateData[i + 1].lat);

      // 获取当前点和下一点的坐标
      const currentPos = Cesium.Cartesian3.fromDegrees(
        coordinateData[i].lon,
        coordinateData[i].lat
      );
      const nextPos = Cesium.Cartesian3.fromDegrees(
        coordinateData[i + 1].lon,
        coordinateData[i + 1].lat
      );
      // 更新位置
      glbEntity.position = nextPos;
      // 计算朝向(从当前点指向下一点的方向)
      const heading = -(computeHeading(currentPos, nextPos));

      // 更新朝向
      glbEntity.orientation = Cesium.Transforms.headingPitchRollQuaternion(
        nextPos,
        new Cesium.HeadingPitchRoll(heading, 0, 0)
      );
      // 更新现有模型的位置,而不是创建新模型
      // glbEntity.position = Cesium.Cartesian3.fromDegrees(
      //   coordinateData[i + 1].lon,
      //   coordinateData[i + 1].lat
      // );
      // 轨迹
      viewer.entities.add({
        id: coordinateData[i + 1].id,
        name: coordinateData[i + 1].name,
        polyline: new Cesium.PolylineGraphics({
          positions: Cesium.Cartesian3.fromDegreesArray(arr),
          width: 5, // 线条宽度
          clampToGround: true, // 贴地显示
          material: Cesium.Color.fromCssColorString("#0f0"), // 线条材质颜色
        }),
      });
      i++;
    } else {
      // 已全部获取
      clearInterval(interval);
      interval = null;
    }
  }, 3000);
}

// 计算两点之间的朝向角(弧度)
function computeHeading(start, end) {
  const direction = Cesium.Cartesian3.subtract(
    end,
    start,
    new Cesium.Cartesian3()
  );
  const up = Cesium.Cartesian3.normalize(start, new Cesium.Cartesian3());

  // 计算东方向(垂直于向上方向和北方向)
  const east = Cesium.Cartesian3.cross(
    new Cesium.Cartesian3(0, 0, 1),
    up,
    new Cesium.Cartesian3()
  );
  Cesium.Cartesian3.normalize(east, east);

  // 计算北方向(垂直于东方向和向上方向)
  const north = Cesium.Cartesian3.cross(up, east, new Cesium.Cartesian3());

  // 计算方向向量在水平面(东-北平面)上的投影
  const horizontalDirection = new Cesium.Cartesian3();
  Cesium.Cartesian3.subtract(
    direction,
    Cesium.Cartesian3.multiplyByScalar(
      up,
      Cesium.Cartesian3.dot(direction, up),
      new Cesium.Cartesian3()
    ),
    horizontalDirection
  );
  Cesium.Cartesian3.normalize(horizontalDirection, horizontalDirection);

  // 计算朝向角(从北方向顺时针旋转的角度)
  const dot = Cesium.Cartesian3.dot(north, horizontalDirection);
  const cross = Cesium.Cartesian3.dot(east, horizontalDirection);
  return Math.atan2(cross, dot);
}

 

glb模型实时轨迹

2、使用图片进行实时轨迹 

111.png

// 使用图片进行实时轨迹
export function addImgTrajectory() {
  // 先添加初始线条
  let arr = [coordinateData[0].lon, coordinateData[0].lat];

  // 添加一个Billboard作为标记
  let billboards  = new Cesium.BillboardGraphics({
      image: "111.png", // 图片路径
      width: 50, // 图片宽度
      height: 50, // 图片高度
      rotation: 0
    })
  let glbEntity = viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(110, 30.0), // 经纬度坐标
    billboard: billboards
  });

  let i = 0;
  interval = setInterval(() => {
    // 当数组下标还有数据时
    if (coordinateData[i + 1]) {
      arr.push(coordinateData[i + 1].lon, coordinateData[i + 1].lat);

      // 更改图片位置
      // 更新现有模型的位置,而不是创建新模型
      glbEntity.position = Cesium.Cartesian3.fromDegrees(
        coordinateData[i + 1].lon,
        coordinateData[i + 1].lat
      );

      let arc = 0;
      if (
        (coordinateData[i + 1].lon - coordinateData[i].lon >= 0 &&
          coordinateData[i + 1].lat - coordinateData[i].lat >= 0) ||
        (coordinateData[i + 1].lon - coordinateData[i].lon < 0 &&
          coordinateData[i + 1].lat - coordinateData[i].lat > 0)
      ) {
        arc = Math.atan(
          (coordinateData[i + 1].lon - coordinateData[i].lon) /
            (coordinateData[i + 1].lat - coordinateData[i].lat)
        );
      } else if (
        (coordinateData[i + 1].lon - coordinateData[i].lon > 0 &&
          coordinateData[i + 1].lat - coordinateData[i].lat < 0) ||
        (coordinateData[i + 1].lon - coordinateData[i].lon < 0 &&
          coordinateData[i + 1].lat - coordinateData[i].lat < 0)
      ) {
        arc =
          Math.PI +
          Math.atan(
            (coordinateData[i + 1].lon - coordinateData[i].lon) /
              (coordinateData[i + 1].lat - coordinateData[i].lat)
          );
      }
      // 更新图片朝向
      glbEntity.billboard.rotation._value = -(arc)

      // 轨迹
      viewer.entities.add({
        id: coordinateData[i + 1].id,
        name: coordinateData[i + 1].name,
        polyline: new Cesium.PolylineGraphics({
          positions: Cesium.Cartesian3.fromDegreesArray(arr),
          width: 5, // 线条宽度
          clampToGround: true, // 贴地显示
          material: Cesium.Color.fromCssColorString("#0f0"), // 线条材质颜色
        }),
      });
      i++;
    } else {
      // 已全部获取
      clearInterval(interval);
      interval = null;
    }
  }, 1000);
}

 

图片实时轨迹

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

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

相关文章

Android基础回顾】六:安卓显示机制Surface 、 SurfaceFlinger、Choreographer

在 Android 系统中&#xff0c;Surface 和 SurfaceFlinger 是图形渲染系统的核心组件&#xff0c;负责屏幕显示内容的合成与管理。它们协同工作&#xff0c;使各种 App 和系统界面能够高效地显示在屏幕上。 1 Surface 是什么&#xff1f; Surface 是一个抽象的图形缓冲区接口…

敏捷开发中如何避免过度加班

在敏捷开发过程中避免过度加班&#xff0c;需要明确敏捷原则、合理规划迭代任务、加强团队沟通、优化流程效率、设定合理的工作负荷、注重团队士气和成员健康。明确敏捷原则&#xff0c;即保证可持续发展的步调&#xff0c;避免频繁地变更需求、过度承诺任务量。合理规划迭代任…

第1章_数据分析认知_知识点笔记

来自&#xff1a;数据分析自学课程-戴戴戴师兄 逐字稿&#xff1a;【课程4.0】第1章_分析认知_知识点笔记 【课程4.0】第1章 分析认知 知识点总结 数据分析的核心价值不是工具&#xff0c;而是用数据驱动业务增长。 一、数据分析的本质认知 数据分析是什么&#xff1f; 不是酷…

111页可编辑精品PPT | 华为业务变革框架及战略级项目管理华为变革管理华为企业变革华为的管理模式案例培训

这份文档是关于华为公司业务变革管理框架&#xff08;BTMS&#xff09;V2.0的详细介绍&#xff0c;涵盖从年度规划到项目执行的全流程管理。BTMS框架通过变革战略规划、年度规划流程、解决方案开发&#xff08;PMOP流程&#xff09;、运作管理流程等多个模块&#xff0c;系统地…

html文字红色粗体,闪烁渐变动画效果

1. 代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>红色粗体闪烁文字表格</title><s…

Linux文件系统详解:从入门到精通

无论是开发高性能应用还是进行系统级编程&#xff0c;文件系统都是我们必须掌握的基础知识。今天&#xff0c;我将带大家深入浅出地了解Linux文件系统的核心概念和工作原理。 一、Linux文件系统概述 Linux文件系统是操作系统中负责管理持久存储设备上数据的子系统。它不仅仅是…

Electron Fiddle使用笔记

文章目录 下载界面示意图保存和打开项目save 和 save as forge project 其他文档打包报错 RequestError: read ECONNRESET 想要打包前端程序&#xff0c;奈何本地环境总是报错&#xff0c;意外发现可以通过electron fiddle直接调试代码。 下载 百度网盘地址&#xff1a; 首次…

企业培训学习考试系统源码 ThinkPHP框架+Uniapp支持多终端适配部署

在数字化转型浪潮下&#xff0c;企业对高效培训与精准考核的需求日益迫切。一套功能完备、多终端适配且易于定制的培训学习考试系统&#xff0c;成为企业提升员工能力、检验培训成果的关键工具。本文给大家分享一款基于 ThinkPHP 框架与 Uniapp 开发的企业培训学习考试系统&…

SpringBoot手动实现流式输出方案整理以及SSE规范输出详解

背景&#xff1a; 最近做流式输出时&#xff0c;一直使用python实现的&#xff0c;应需求方的要求&#xff0c;需要通过java应用做一次封装并在java侧完成系统鉴权、模型鉴权等功能后才能真正去调用智能体应用&#xff0c;基于此调研java实现流式输出的几种方式&#xff0c;并…

深入解析I²C总线接口:从基础到应用

IC总线概述与基本概念 一句话概述&#xff1a;本章节将介绍IC总线的历史、定义及其在嵌入式系统中的作用&#xff0c;帮助读者建立对IC的基本理解。 IC&#xff08;Inter-Integrated Circuit&#xff09;总线是一种广泛应用于嵌入式系统中的串行通信协议&#xff0c;最初由飞利…

Sklearn 机器学习 缺失值处理 检测数据每列的缺失值

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在代码与灵感交织的数字世界里和大家相遇~💖 ✨ 在这个技术浪潮奔涌的时代,我们既是探索者,也是分享者。我始终相信,每一行代码都是通往创新的钥匙,而分享则能让这把钥匙照亮更多人的…

STL解析——list的使用

目录 1.简介 2.构造函数 3.迭代器 3.1封装 3.2迭代器分类 4.排序性能 4.1链式与数组 4.2缓存读取 1.简介 STL容器中提供的list容器也是一种顺序容器&#xff0c;底层实现方式是带头双向链表&#xff0c;这种实现方式能比单链表更高效的访问数据。 下面围绕部分重要接口…

MQTTX连接阿里云的物联网配置

本文的目标是通过MQTTX的客户端&#xff0c;连接到阿里云的物联网的平台&#xff0c;发送温度信息&#xff0c;在阿里云的平台中显示出来。阿里云免费注册&#xff0c;免费有一个MQTT的服务器。有数量限制&#xff0c;但是对于测试来讲&#xff0c;已经足够。 1、注册阿里云的物…

20250606-C#知识:匿名函数、Lambda表达式与闭包

C#知识&#xff1a;匿名方法、Lambda表达式与闭包 闭包乍一听感觉很复杂&#xff0c;其实一点也不简单 1、匿名方法 没有方法名的方法一般用于委托和事件 Func<int, int, int> myAction delegate(int a, int b) { return a b; }; Console.WriteLine( myAction(1, 2)…

衡量嵌入向量的相似性的方法

衡量嵌入向量的相似性的方法 一、常见相似性计算方法对比 方法核心原理公式优点缺点适用场景余弦相似度计算向量夹角的余弦值,衡量方向相似性,与向量长度无关。$\text{cos}\theta = \frac{\mathbf{a} \cdot \mathbf{b}}{\mathbf{a}\mathbf{b}欧氏距离计算向量空间中的直线距离…

API是什么意思?如何实现开放API?

目录 一、API 是什么 &#xff08;一&#xff09;API 的定义 &#xff08;二&#xff09;API 的作用 二、API 的类型 &#xff08;一&#xff09;Web API 1. RESTful API 2. SOAP API &#xff08;二&#xff09;操作系统 API &#xff08;三&#xff09;数据库 API …

Python训练第四十六天

DAY 46 通道注意力(SE注意力) 知识点回顾&#xff1a; 不同CNN层的特征图&#xff1a;不同通道的特征图什么是注意力&#xff1a;注意力家族&#xff0c;类似于动物园&#xff0c;都是不同的模块&#xff0c;好不好试了才知道。通道注意力&#xff1a;模型的定义和插入的位置通…

第2天:认识LSTM

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目标 具体实现 &#xff08;一&#xff09;环境 语言环境&#xff1a;Python 3.10 编 译 器: PyCharm 框 架: pytorch &#xff08;二&#xff09;具体步骤…

自动化提示生成框架(AutoPrompt)

自动化提示生成框架(AutoPrompt) 一、核心创新点 自动化提示生成框架(AutoPrompt) 创新本质:提出基于梯度引导搜索的自动化提示生成方法,替代人工设计模板的传统模式。技术路径: 将提示视为可训练的离散token序列,通过优化提示向量(prompt embedding)搜索语义空间。利…

中国首套1公里高分辨率大气湿度指数数据集(2003~2020)

时间分辨率&#xff1a;月空间分辨率&#xff1a;100m - 1km共享方式&#xff1a;开放获取数据大小&#xff1a;34.79 GB数据时间范围&#xff1a;2003-01-01 — 2020-12-31元数据更新时间&#xff1a;2023-07-26 数据集摘要 中国首套1公里高分辨率大气湿度指数数据集&#xf…