4.Cesium中实体Entity的增删改查及性能优化(超详细)

news2024/11/27 2:34:59

banner

前言

Cesium 作为一个功能强大的 WebGL 三维地球仪库,内置了丰富的三维地图展示能力。在 Cesium 中,我们可以通过 Entity(实体)在三维场景中添加和控制各种三维对象,如点、线、面、模型等。本文将介绍 Cesium 中实体的增删改查操作。

概述

添加到场景中的实体都保存在 viewer.entities 中。我们在控制台中输出 viewer.entities,在其原型对象上寻找对应的处理方法,下面是操作代码:

  const token = import.meta.env.VITE_CESIUM_TOKEN;
  Cesium.Ion.defaultAccessToken = token;
  const viewer = new Cesium.Viewer("cesiumContainer", {
    //图层控件显隐控制
    timeline: false, //隐藏时间轴
    animation: false, //隐藏动画控制器
    geocoder: false, //隐藏地名查找控制器
    homeButton: false, //隐藏Home按钮
    sceneModePicker: false, //隐藏投影方式控制器
    baseLayerPicker: false, //隐藏图层选择控制器
    navigationHelpButton: false, //隐藏帮助按钮
    fullscreenButton: false, //隐藏全屏按钮
  });
  global.$viewer = viewer;
  //创建一个立方体
  const box = new Cesium.Entity({
    id:"box",
    position: Cesium.Cartesian3.fromDegrees(114.3, 39.9, 20000),
    box: {
      dimensions: new Cesium.Cartesian3(40000, 30000, 10000), //盒子的长宽高
      material: Cesium.Color.RED, //盒子颜色
      outline: true, //边框
      outlineColor: Cesium.Color.WHITE, //边框颜色
    },
  });
  
  //将立方体添加到场景中
  const boxEntity = viewer.Entities.Add (box);
  
  //视角飞行至立方体
  viewer.camera.flyTo(
    {
      destination: Cesium.Cartesian3.fromDegrees(114.3, 39.9, 40000), // 目的地的经纬度坐标
      duration: 4,
    } // 动画持续时间,默认为3秒
  );
	//输出viewer.entities
  console.log(viewer.entities);
});

可以看到有以下entity属性和方法,我将根据这些方法进行entity操作:
entities
我们可以总结出如下思维导图:
思维导图

一、实体的添加

在Cesium中,我们可以通过两种方式添加实体。

1 .直接添加

const viewer = new Cesium.Viewer("cesiumContainer", {
//相关配置代码...
  });
  viewer.entities.add({
    id: "point",
    position: Cesium.Cartesian3.fromDegrees(116.3, 39.9),
    point: {
      pixelSize: 10,//点像素大小
      color: Cesium.Color.RED,//点颜色,不能用rgb等css方法,需要用Cesium.Color
      outlineColor: Cesium.Color.WHITE,
      outlineWidth: 2,
    },
  });

2 .先创建后添加

const viewer = new Cesium.Viewer("cesiumContainer", {
//相关配置代码...
 });
const point = new Cesium.Entity({
   position: Cesium.Cartesian3.fromDegrees(116.3, 39.9),
   point: {
     pixelSize: 10,//点像素大小
     color: Cesium.Color.RED,//点颜色,不能用rgb等css方法,需要用Cesium.Color
     outlineColor: Cesium.Color.WHITE,
     outlineWidth: 2,
   },
 });
viewer.entities.add(point);

这里我们没有使用了 new 关键字对 Cesium 的 Entity 类进行实例化;但是有细心的读者可能会发现,即使不用 new Cesium. Entity (), 只定义一个对象,实体 box 照样可以加入到 viewer 空间中,这是因为我们使用了下面这行代码:

viewer.entities.add({...})

在 Cesium 中,viewer.entities.add() 方法可以接受一个 Entity 实例或一个对象字面量作为参数。如果传递的是一个对象字面量,Cesium 会自动将其转换为一个 Entity 实例。因此,即使你没有显式地使用 new Cesium.Entity() 来创建一个 Entity 实例,也可以正常运行。

建议当创建代码和添加代码分开时采用类创建,一体时采用字面量创建,以便更加清楚的表明自己的意图,使代码更容易阅读和维护。

二、实体的删除

关于删除实体的方法有 remove,removeAll, removeById; 我将分别进行介绍:

1 . 删除特定实体

我们在上面添加实体的代码中定义了对应的实体变量 boxEntity,这里我们通过以下代码删除:

viewer.entities.remove(boxEntity);//如果已删除则返回true,如果该集合中不存在该实体,则返回false

2 . 删除所有点

viewer.entities.removeAll();//如果已删除则返回true,如果该集合为空,则返回false

3 . 根据 id 删除点

viewer.entities.removeById("box");//如果已删除则返回true,如果该集合中不存在该实体,则返回false

4 . 先获取实体,再删除

const box  = viewer.entites.getById("box");
viewer.entities.remove(box);

5 . 自定义删除

因为 viewer. Entities 是按照输入的实体对象进行删除的,我们可以创建一个数组存储实体对象,然后根据数组方法遍历实体对象对其进行删除;代码如下:

let list1 = [];
let list2 = [];

const box1 = new Cesium.Entity({
    id:"box",
    position: Cesium.Cartesian3.fromDegrees(114.3, 39.9, 20000),
    box: {
      dimensions: new Cesium.Cartesian3(40000, 30000, 10000), //盒子的长宽高
      material: Cesium.Color.RED, //盒子颜色
      outline: true, //边框
      outlineColor: Cesium.Color.WHITE, //边框颜色
    },
  });
  
viewer.entities.add(box1);
list1.push(box1);

const box2 = new Cesium.Entity({
    id:"box",
    position: Cesium.Cartesian3.fromDegrees(114.3, 39.9, 20000),
    box: {
      dimensions: new Cesium.Cartesian3(40000, 30000, 10000), //盒子的长宽高
      material: Cesium.Color.RED, //盒子颜色
      outline: true, //边框
      outlineColor: Cesium.Color.WHITE, //边框颜色
    },
  });
  
list2.push(box2);
viewer.entities.add(box2);

//要删除某个类别,只需要遍历对应的数组进行删除即可
list1.forEach((item)={
  viewer.entities.remove(item)})
 
//也可以在数组循环中设定条件针对删除;
list2.forEach((item)={
  if(item.id=="box"){
    viewer.entities.remove(item)}
})

三、实体的修改

我们可以通过CallbackProperty回调属性实现实体的动态修改;使用代码如下:

 //创建一个呼吸小球
  const ellipsoid = new Cesium.Entity({
    position: Cesium.Cartesian3.fromDegrees(114.3, 39.9),
    ellipsoid: {
      //radii是radius的复数,因为这个创建的是椭球体,所以要设定三个轴的长度一致,即可构成球体;
      radii: new Cesium.CallbackProperty(function () { 
        //呼吸小球
        var radius =
          10000 + Math.sin(Cesium.JulianDate.now().secondsOfDay) * 3000;//根据sin 函数和 时间变量实现动态半径变化;
        return new Cesium.Cartesian3(radius, radius, radius);
      }, false),
      heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,//实体底部贴地
      material: Cesium.Color.RED.withAlpha(0.5),
    },
  });
  
  //将立方体添加到场景中
  const boxEntity = viewer.entities.add(ellipsoid);
  
  //视角飞行至立方体
  viewer.camera.flyTo(
    {
      destination: Cesium.Cartesian3.fromDegrees(114.3, 39.9, 40000), // 目的地的经纬度坐标
      duration: 4,
    } // 动画持续时间,默认为3秒
  );

在这里插入图片描述

  • CallbackProperty,可以看作是一个特殊的属性类型,参数是被封装好的回调函数;会持续执行。
  • 当开发者使用 new Cesium.CallbackProperty(callback) 创建一个回调属性并将其应用于场景中的某个元素(例如立方体)时,Cesium 会在渲染过程中不断获取这个回调属性的值。每次 Cesium 需要获取这个回调属性的值时,它都会调用这个回调函数,并使用返回的值作为属性值。
  • 这个过程并不需要你显式地编写循环。相反,它是由 Cesium 内部的渲染引擎自动触发的。当 Cesium 渲染场景时,它会不断更新场景中的各个元素,并在需要时获取回调属性的值。
  • 因此,即使你没有显式地编写循环,Cesium 也会在渲染过程中多次调用回调函数来计算属性值。它并不是只计算一次,而是每次 Cesium 需要获取这个属性的值时都会调用回调函数来计算属性值。因此,开发者可以使用 Cesium.CallbackProperty 来实现各种动态效果。

四、实体的查询

Cesium 中,我们可以通过以下方法查询实体:

1.通过 getById 根据 id 查询

const box  = viewer.entites.getById("box");

2.通过 getOrCreateEntity 根据 id 查询

如果该 id 对应的实体不存在,则将其添加到集合中。

const entity  = viewer.entites.getOrCreateEntity (id);

3.通过 contains 判断实体是否存在

const isExist = viewer.entities.contains (entity)//如果实体存在,则返回true,否则返回false;

五、性能优化

在批量添加或修改实体时,可以使用viewer.entities.suspendEvents()viewer.entities.resumeEvents()方法来提高性能。这两个方法分别用于暂停和恢复 Cesium 实体集合的事件处理。

开发者可以在批量更新之前调用 viewer.entities.suspendEvents() 来暂停事件处理,然后在更新完成后调用 viewer.entities.resumeEvents() 来恢复事件处理。

案例代码如下:

// 暂停事件处理
viewer.entities.suspendEvents();

// 执行批量更新
for (let i = 0; i < 1000; i++) {
  viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(Math.random() * 360 - 180, Math.random() * 180 - 90),
    point: {
      pixelSize: 10,
      color: Cesium.Color.RED,
    },
  });
}

// 恢复事件处理
viewer.entities.resumeEvents();

  • 当开发者调用 viewer.entities.suspendEvents() 时,Cesium 会暂停实体集合的事件处理。这意味着在暂停期间,Cesium 不会触发与实体相关的事件,例如 definitionChanged 事件。这可以提高批量添加或更新实体时的性能。
  • 在暂停事件处理期间,用户仍然可以继续向实体集合中添加、删除或更新实体。这些操作不会受到暂停事件处理的影响。但是,在暂停事件处理期间,Cesium 不会触发与实体相关的事件。这意味着如果您在暂停期间对实体进行了更改,那么这些更改不会立即反映在场景中。
  • 当用户调用 viewer.entities.resumeEvents() 时,Cesium 会恢复实体集合的事件处理。这意味着 Cesium 会重新开始触发与实体相关的事件。如果您在暂停期间对实体进行了更改,那么在恢复事件处理后,Cesium 会触发相应的事件来反映这些更改。

Tips

viewer.entities.suspendEvents()viewer.entities.resumeEvents() 这两个方法只能用于暂停和恢复 Cesium 实体集合的事件处理。它们只能用于控制与实体相关的事件,不能用于控制场景中其他元素的事件。

六、计算时间间隔

1 .应用场景

computeAvailability() 方法的一个具体应用场景是在使用 CZML 数据源时。CZML 是一种用于描述时间动态图形的 JSON 格式。它允许你定义随时间变化的实体,例如卫星轨迹或飞机飞行路径。

2. 使用细节

当开发者使用 CZML 数据源加载 CZML 数据时,Cesium 会根据 CZML 数据创建实体集合。每个实体都可以具有可用性时间间隔,表示实体在何时可见或有效。这个时候可以使用 computeAvailability() 方法来计算整个实体集合的可用性时间间隔。计算得到的可用性时间间隔表示实体集合在给定时间范围内的可用性。这个信息可以帮助你更好地控制场景中的元素。例如,你可以使用这个信息来确定何时显示或隐藏与实体集合相关的其他元素,或者调整场景的时间轴以查看实体集合。

3 . 代码案例

var viewer = new Cesium.Viewer("cesiumContainer");
var scene = viewer.scene;

// 加载 CZML 数据
var czml = [
  {
    id: "document",
    name: "CZML Path",
    version: "1.0",
  },
  {
    id: "path",
    name: "path with GPS flight data",
    availability: "2022-08-04T16:00:00Z/2023-08-04T16:02:00Z",
    position: {
      epoch: "2022-08-04T16:00:00Z",
      cartographicDegrees: [
        0, -117.0, 35.0, 100000, 30, -117.0, 36.0, 100000, 60, -117.0, 37.0,
        100000, 90, -117.0, 38.0, 100000, 120, -117.0, 39.0, 100000,
      ],
    },
    path: {
      material: {
        solidColor: {
          color: {
            rgba: [255, 255, 0, 255],
          },
        },
      },
      width: 5,
      leadTime: 10,
      trailTime: 1000,
      resolution: 5,
    },
  },
];
  
  var dataSource = Cesium.CzmlDataSource.load(czml);
  viewer.dataSources.add(dataSource).then(function (dataSource) {
  var entityCollection = dataSource.entities;
  
  // 计算实体集合的可用性时间间隔
  var availability = entityCollection.computeAvailability();
  // 创建标签实体
  var labelEntity = viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(-117.0, 35.0, 100000),
    label: {
      text: "Satellite in view",
      show: false,
    },
  });

    // 监听场景的 preRender 事件
  scene.preRender.addEventListener(function () {
    var currentTime = Cesium.JulianDate.fromDate(new Date());
    // 判断当前时间是否在可用性时间间隔内
    if (
      Cesium.JulianDate.greaterThanOrEquals(
        currentTime,
        availability.start
      ) &&
      Cesium.JulianDate.lessThanOrEquals(currentTime, availability.stop)
    ) {
      // console.log(availability.start, availability.stop, currentTime);
      // 如果在可用性时间间隔内,则显示标签实体
      labelEntity.label.show = true;
    } else {
      // 如果不在可用性时间间隔内,则隐藏标签实体
      labelEntity.label.show = false;
    }
  });
});
    1. 这段代码加载了一个包含路径数据的 CZML 文件,并使用 Cesium.CzmlDataSource.load 方法将其转换为数据源。然后,它调用 viewer.dataSources.add 方法将数据
    1. 添加到场景中。当数据源加载完成后,它使用 computeAvailability() 方法来计算实体集合的可用性时间间隔。
    1. 接着,这段代码创建了一个标签实体,并将其添加到场景中。标签实体的初始状态为隐藏。
    1. 然后,这段代码使用 scene.preRender.addEventListener 方法来监听场景的渲染事件。在事件处理函数中,它获取当前时间,并判断当前时间是否在可用性时间间隔内。如果当前时间在可用性时间间隔内,则显示标签实体;否则,隐藏标签实体。
      compute

当前是 2023 年,结束时间是 2022 年,标签不可见,将结束时间改为 2023 年后,标签可见;

CZML数据解释:

每四个元素表示一个数据点,第一个元素是相对于 epoch 的时间偏移量,后三个元素分别表示经度、纬度和高度。
第一个数据点的时间偏移量为 0,表示它的时间值为 2012-08-04T16:00:00Z + 0 = 2012-08-04T16:00:00Z。第二个数据点的时间偏移量为 30,表示它的时间值为 2012-08-04T16:00:00Z + 30 = 2012-08-04T16:00:30Z
"2012-08-04T16:00:00Z/2012-08-04T16:02:00Z" 意味着实体只在 2012-08-04T16:00:00Z2012-08-04T16:02:00Z 之间对观察者可见。在这个时间范围之外,实体不会显示在场景中。

总结

综上,本文系统介绍了 Cesium 开发中实体各种增删改查的操作方法,内容全面且重点突出,可以作为 Cesium 实体操作的指南,希望对 Cesium 开发者有所裨益。

项目地址

Github地址
Gitee地址
拓展阅读
专栏地址


如果觉得我的文章对您有帮助,三连+关注便是对我创作的最大鼓励!或者一个star🌟也可以😂.

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

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

相关文章

【AI绘画】Stable-Diffusion-Webui本地部署-简单绘画图片

这里写目录标题 前言一、Stable Diffusion是什么&#xff1f;二、安装stable-diffusion-webui1. python安装2. 下载模型3. 开始安装&#xff1a;4. 汉化&#xff1a;5. 模型使用&#xff1a;6. 下载新模型&#xff1a;7. 基础玩法 三、总结 前言 本文将借助stable-diffusion-w…

【idea】的一些使用指南

一、serializable自动生成id 1.打开File菜单&#xff0c;选择Settings选项 2.打开Editor->Inspections 3.在右边的搜索框中输入serialVersionUID关键字&#xff0c;出现以下选项&#xff0c;勾选"Serializable class without serialVersionUID"&#xff0c;然后别…

攻不下dfs不参加比赛(十)

标题 为什么练dfs题目总结为什么练dfs 相信学过数据结构的朋友都知道dfs(深度优先搜索)是里面相当重要的一种搜索算法,可能直接说大家感受不到有条件的大家可以去看看一些算法比赛。这些比赛中每一届或多或少都会牵扯到dfs,可能提到dfs大家都知道但是我们为了避免眼高手低有…

非监督学习-K均值聚类-知识点扫盲

前言 在实际工作中&#xff0c;我们经常会遇到这样一类问题&#xff1a;给机器输入大量的特征数据&#xff0c;并期望机器通过学习找到数据中存在的某种共性特征或者结构&#xff0c;亦或是数据之间存在的某种关联。 例如&#xff0c;视频网站根据用户的观看行为对用户进行分组…

【MongoDB】SpringBoot整合MongoDB

【MongoDB】SpringBoot整合MongoDB 文章目录 【MongoDB】SpringBoot整合MongoDB0. 准备工作1. 集合操作1.1 创建集合1.2 删除集合 2. 相关注解3. 文档操作3.1 添加文档3.2 批量添加文档3.3 查询文档3.3.1 查询所有文档3.3.2 根据id查询3.3.3 等值查询3.3.4 范围查询3.3.5 and查…

8、gateway使用和原理

一、什么是Spring Cloud Gateway 1、网关简介 网关作为流量的入口&#xff0c;常用的功能包括路由转发&#xff0c;权限校验&#xff0c;限流等。 2、Gateway简介 Spring Cloud Gateway 是Spring Cloud官方推出的第二代网关框架&#xff0c;定位于取代 Netflix Zuul。相比 …

【iOS】编译与链接过程

前言 计算机语言分为&#xff1a;机器语言、汇编语言和高级语言。 高级语言又能分为&#xff1a;编辑语言、解释语言。 解释语言 解释语言编写的程序在每次运行时都需要通过解释器对程序进行动态解释和执行&#xff0c;即解释一条代码&#xff0c;执行一条代码。 优点&…

ADC 的初识

ADC介绍 Q: ADC是什么&#xff1f; A: 全称&#xff1a;Analog-to-Digital Converter&#xff0c;指模拟/数字转换器 ADC的性能指标 量程&#xff1a;能测量的电压范围分辨率&#xff1a;ADC能辨别的最小模拟量&#xff0c;通常以输出二进制数的位数表示&#xff0c;比如&am…

一百三十、海豚调度器——用DolphinScheduler定时调度HiveSQL任务

一、目标 用海豚调度器对Hive数仓各层数据库的SQL任务进行定时调度。比如&#xff0c;DWD层脱敏清洗表的动态插入数据、DWS层指标表的动态插入数据 二、工具版本 1、海豚调度器&#xff1a;apache-dolphinscheduler-2.0.5-bin.tar.gz 2、Hive&#xff1a;apache-hive-3.1.2…

随手笔记——Sophus的基本使用方法

随手笔记——Sophus的基本使用方法 说明CMakeLists.txt补充&#xff1a;关于 ADD_SUBDIRECTORY 的使用使用CMakeLists执行顺序 源代码 说明 Sophus 库支持SO(3) 和SE(3)&#xff0c;此外还含有二维运动 SO(2)&#xff0c;SE(2) 以及相似变换 Sim(3) 的内容。它是直接在 Eigen …

数据结构--图的存储邻接矩阵法

数据结构–图的存储邻接矩阵法 无向图&#xff1a; 有向图&#xff1a; #define MaxVerTexNum 100 //顶点数目的最大值 typedef struct {char vex[MaxVerTexNum]; //顶点表int Edge[MaxVerTexNum][MaxVerTexNum]; //邻接矩阵&#xff0c;边表int vexnum, arcnum; //图的当前顶…

最新 robot framework安装

相信大家对robot framework并不陌生&#xff0c;它是一个基于Python语言&#xff0c;用于验收测试和验收测试驱动开发&#xff08;ATDD&#xff09;的通用测试自动化框架&#xff0c;提供了一套特定的语法&#xff0c;并且有非常丰富的测试库。 ### [Python](https://www.pytho…

gogs的自定义配置

在 GOGS 下载并安装后&#xff0c;在程序目录下建立一个custom/conf/app.ini的配置文件&#xff0c;内容如下&#xff1a; APP_NAME Gogs # APP名字 RUN_USER git # 启动用户&#xff0c;设置后只能以此账号启动gogs RUN_MODE prod[database] DB_TYPE mysql HOST 1…

联通 Flink 实时计算平台化运维实践

摘要&#xff1a;本文整理自联通数科实时计算团队负责人、Apache StreamPark Committer 穆纯进在 Flink Forward Asia 2022 平台建设专场的分享&#xff0c;本篇内容主要分为四个部分&#xff1a; 实时计算平台背景介绍 Flink 实时作业运维挑战 基于 StreamPark 一体化管理 …

智能安全配电装置在老旧建筑防火中的应用 安科瑞 许敏

【摘要】现代社会的发展离不开电能&#xff0c;随着电能应用的广泛性&#xff0c;对用电安全有了更高的要求。近些年来&#xff0c;用电安全形式严峻&#xff0c;尤其是一些老旧建筑中因用电而引起的火灾事故频发&#xff0c;造成一系列严重的损失&#xff0c;严重影响着民众的…

rancher部署

Rancher 管理 Kubernetes 集群 //Rancher 简介 Rancher 是一个开源的企业级多集群 Kubernetes 管理平台&#xff0c;实现了 Kubernetes 集群在混合云本地数据中心的集中部署与管理&#xff0c; 以确保集群的安全性&#xff0c;加速企业数字化转型。超过 40000 家企业每天使用 …

工控机设备安全

工控设备安全现状 工业控制系统是支撑国民经济的重要设施&#xff0c;是工业领域的神经中枢。现在工业控制系统已经广泛应用于电力、通信、化工、交通、航天等工业领域&#xff0c;支撑起国计民生的关键基础设施。 随着传统的工业转型&#xff0c;数字化、网络化和智能化的工…

C++11(3)——lambda表达式

目录 1 C98中的一个例子 2 lambda表达式 3 lambda表达式语法 4 函数对象与lambda表达式 1 C98中的一个例子 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用std::sort方法。 如果待排序元素为自定义类型&#xff0c;需要用户定义排序时的…

vue新增删除内容排序问题解决处理

本次答题选项的删除添加是个人最初比较头疼的地方。比如ABCD四个选项&#xff0c;删除c选项后&#xff0c;点击【新增答题类型】选项按钮&#xff0c;则默认创建是E选项。再或者就是ABCD四个选项位置删除任意一个后&#xff0c;顺序被打乱等&#xff0c;最后解决了&#xff0c;…

每日刷一题——二维数组中的查找

二维数组中的查找 原题链接&#xff1a;JZ4 二维数组中的查找 问题描述 在一个二维数组中&#xff08;每个一维数组的长度相同&#xff09;&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个函数&#xff0c;输入…