当前位置: 首页 > news >正文

【Cesium开发实战】火灾疏散功能的实现,可设置火源点、疏散路径、疏散人数

Cesium有很多很强大的功能,可以在地球上实现很多炫酷的3D效果。今天给大家分享一个可自定义的火灾疏散人群的功能。

1.话不多说,先展示

火灾疏散模拟

2.设计思路

根据项目需求要求,可设置火源点、绘制逃生路线、可设置逃生人数。所以点击火灾点绘制后,在地图点击可看到火光的粒子效果。点击疏散路径绘制后,在地图上点击可以绘制路径,双击结束绘制,一个火灾点会有多条疏散路径,可再次同样步骤操作绘制路径,点击保存可编辑名称和设定每条路径疏散的人数数量形成列表数据,点击开始疏散,通过czml数据格式实现疏散动画效果。

3.具体代码

<template><div class="page"><el-button @click="drawStartPosition">火灾点绘制</el-button><el-button @click="drawLineRoad">疏散路径绘制</el-button><el-button @click="save">保存</el-button><div style="margin-top: 10px"><el-table :data="dataList" border @row-click="rowClick"><el-table-column prop="name" label="名称" align="center" /><el-table-column label="操作" align="center"><template #default="scope"><el-button type="primary" style="width: 50px;"@click="startShus(scope.row, scope.$index)">开始疏散</el-button><el-button link type="primary" size="small" @click="delEntity(scope.row, scope.$index)"><el-icon:size="16"><ele-Delete /> </el-icon></el-button></template></el-table-column></el-table></div><el-dialog v-model="dialogFormVisible" title="配置" width="500" :close-on-press-escape="false":close-on-click-modal="false" :show-close="false"><el-form ref="formRef" :model="form" label-width="auto" class="demo-dynamic" :rules="rules"><el-form-item label="疏散名称" prop="title"><el-input v-model="form.title" placeholder="请输入" /></el-form-item><el-form-item label="疏散路线人数"><el-input-number :min="0" v-model="form.people" placeholder="请输入" /></el-form-item></el-form><template #footer><div class="dialog-footer"><el-button type="primary" @click="submitForm(formRef)"> 确定 </el-button></div></template></el-dialog></div>
</template><script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref } from 'vue';
import { Cesium } from '/@/utils/cesium';
const props = defineProps(['viewer']);//是否显示弹框
const dialogFormVisible = ref(false);const formRef = ref();var entities: any = {};const rules = {title: { required: true, message: '请输入疏散名称', trigger: 'blur' },
};// 视图名称
const form = reactive({title: '',people: 20,
});// 视点列表数据
const dataList: any = reactive([]);/*** 点击表格一行*/
const rowClick = (row: any, column: any, event: Event) => {if (column && column.property) {let index = dataList.findIndex((v: any) => v.id === row.id);if (index !== -1) {props.viewer.flyTo(listEntities[index].entities[0].pointEntities[0], {offset: {heading: Cesium.Math.toRadians(10.0114629015290062),pitch: Cesium.Math.toRadians(-23.53661660731824),roll: Cesium.Math.toRadians(0.00324596311071617),},});}}
};//是否开始绘制火灾点
const drawing = ref(false);
var firePointEntity: any = [];
var firePrimitiveEntity: any = [];
//绘制火灾起点
const drawStartPosition = () => {drawing.value = true;var handler2 = new Cesium.ScreenSpaceEventHandler(props.viewer.scene.canvas);//鼠标左键handler2.setInputAction(function (event: any) {if (drawing.value) {var earthPosition = props.viewer.scene.pickPosition(event.position);if (Cesium.defined(earthPosition)) {//将笛卡尔坐标转化为经纬度坐标var cartographic = Cesium.Cartographic.fromCartesian(earthPosition);var longitude = Cesium.Math.toDegrees(cartographic.longitude);var latitude = Cesium.Math.toDegrees(cartographic.latitude);var height = cartographic.height;var entity44 = props.viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),});//存储火灾点点位对象到集合firePointEntity.push(entity44);var firePrimitive = new Cesium.ParticleSystem({image: '/src/assets/cesium/fire.png',startColor: Cesium.Color.RED.withAlpha(0.7),endColor: Cesium.Color.YELLOW.withAlpha(0.3),startScale: 0,endScale: 10,minimumParticleLife: 1,maximumParticleLife: 6,minimumSpeed: 1,maximumSpeed: 4,imageSize: new Cesium.Cartesian2(55, 55),// Particles per second.emissionRate: 4,lifetime: 160.0,emitter: new Cesium.CircleEmitter(5.0),modelMatrix: computeModelMatrix(entity44, Cesium.JulianDate.now()),emitterModelMatrix: computeEmitterModelMatrix()});props.viewer.scene.primitives.add(firePrimitive);//存储火灾点图像对象到集合firePrimitiveEntity.push(firePrimitive);//移除左键监听handler2.destroy();// 确保视角没有被锁定  props.viewer.trackedEntity = undefined;}}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}const computeModelMatrix = (entity: any, time: any) => {var position = entity.position.getValue(Cesium.JulianDate.now());let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position);return modelMatrix;
}
const computeEmitterModelMatrix = () => {let hpr = Cesium.HeadingPitchRoll.fromDegrees(0, 0, 0);let trs = new Cesium.TranslationRotationScale();trs.translation = Cesium.Cartesian3.fromElements(2.5, 4, 1);trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr);let result = Cesium.Matrix4.fromTranslationRotationScale(trs);return result
}// 弧度转角度
const toDegrees = (radians: any) => {return (radians * 180) / Math.PI;
};//是否开始绘制火灾点
const drawingLine = ref(false);
var listEntities: any = [];
//绘制的所有地面的点线实体集合
var entities: any = [];
//临时一条数据的point实体列表
var pointEntities: any = [];
//临时一条数据的线实体列表
var linesEntities: any = [];
var activeShapePoints: any = [];
var floatingPoint: any = undefined;
var activeShape: any = undefined;
//绘制线路
const drawLineRoad = () => {drawingLine.value = true;var handler = new Cesium.ScreenSpaceEventHandler(props.viewer.scene.canvas);//鼠标左键handler.setInputAction(function (event: any) {if (drawingLine.value) {var earthPosition = props.viewer.scene.pickPosition(event.position);if (Cesium.defined(earthPosition)) {if (activeShapePoints.length === 0) {floatingPoint = createPoint(earthPosition);activeShapePoints.push(earthPosition);var dynamicPositions = new Cesium.CallbackProperty(function () {return activeShapePoints;}, false);activeShape = drawShape(dynamicPositions); //绘制动态图//线实体集合linesEntities.push(activeShape);}activeShapePoints.push(earthPosition);//点实体集合pointEntities.push(createPoint(earthPosition));}}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);//鼠标移动handler.setInputAction(function (event: any) {if (Cesium.defined(floatingPoint)) {var newPosition = props.viewer.scene.pickPosition(event.endPosition);if (Cesium.defined(newPosition)) {floatingPoint.position.setValue(newPosition);activeShapePoints.pop();activeShapePoints.push(newPosition);}}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);handler.setInputAction(function () {if (drawingLine.value) {drawingLine.value = false;terminateShape();}//移除监听handler.destroy();// 确保视角没有被锁定  props.viewer.trackedEntity = undefined;}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
};//绘制点
const createPoint = (worldPosition: any) => {var point = props.viewer.entities.add({position: worldPosition,point: {color: Cesium.Color.RED,pixelSize: 10,heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,},});return point;
};//绘制线
const drawShape = (positionData: any) => {var shape = props.viewer.entities.add({polyline: {with: 10,color: Cesium.Color.RED,positions: positionData,clampToGround: true,},});return shape;
};//双击后处理数据
const terminateShape = () => {linesEntities.push(drawShape(activeShapePoints)); //绘制最终图//因双击会触发俩次单机事件,去除最后一个点重复绘制,并删除多余的点props.viewer.entities.remove(pointEntities[pointEntities.length - 1]);pointEntities.pop();props.viewer.entities.remove(floatingPoint); //去除动态点图形(当前鼠标点)props.viewer.entities.remove(activeShape); //去除动态图形floatingPoint = undefined;activeShape = undefined;activeShapePoints = [];//点实体和线实体的集合entities.push({pointEntities: pointEntities,linesEntities: linesEntities,});pointEntities = [];linesEntities = [];
};//保存火灾点和疏散路径
var customMarks: any = [];
const save = () => {dialogFormVisible.value = true; //弹出对话框
}/*** 点击确定绘制*/
const submitForm = async (formEl: any) => {const valid = await formEl.validate();if (valid) {listEntities.push({firePointEntity: firePointEntity,firePrimitiveEntity: firePrimitiveEntity,entities: entities});dataList.push({id: new Date().getTime(),name: form.title,people:form.people});//设置为空对象以便创建新的列表数据firePointEntity = [];firePrimitiveEntity = [];entities = [];dialogFormVisible.value = false;form.title = '';}
};/*** 删除列表数据*/
const delEntity = (item: any, index: number) => {for (const item of listEntities[index].firePointEntity) {props.viewer.entities.remove(item);}for (const item of listEntities[index].firePrimitiveEntity) {props.viewer.scene.primitives.remove(item);}for (const iterator of listEntities[index].entities) {for (const item of iterator.pointEntities) {props.viewer.entities.remove(item);}for (const item of iterator.linesEntities) {props.viewer.entities.remove(item);}}dataList.splice(index, 1);listEntities.splice(index, 1);if (obj) {props.viewer.dataSources.remove(obj);obj = null;}};var obj: any;//开始疏散
const startShus = (item: any, index: number) => {var czml: any = [];czml.push({"id": "document","name": "CZML Path","version": "1.0"});var entities = listEntities[index].entities;var peopleNum = item.people;if (entities.length) {for (const [index2, item2] of entities.entries()) {customMarks = [];for (const [index, item] of item2.pointEntities.entries()) {const latitude = toDegrees(Cesium.Cartographic.fromCartesian(item.position._value).latitude);const longitude = toDegrees(Cesium.Cartographic.fromCartesian(item.position._value).longitude);customMarks.push((1 * index));customMarks.push(longitude);customMarks.push(latitude);customMarks.push(2);}for (let i = 0; i < peopleNum; ++i) {var iso8601DateString = '2024-07-04T10:00:00Z';var julianDate = Cesium.JulianDate.fromIso8601(iso8601DateString);if (Cesium.defined(julianDate)) {var newJulianDate = Cesium.JulianDate.addSeconds(julianDate, i * 0.5, new Cesium.JulianDate());// 如果你需要将 JulianDate 转换为 Date 对象  var date = Cesium.JulianDate.toDate(newJulianDate);czml.push({"id": "path" + index2 + i,"name": "路径" + index2 + i,"availability": "2024-07-04T10:00:00.000Z/2024-07-04T10:01:00.000Z","model": {id: 'man',gltf: '/src/assets/cesium/Cesium_Man.glb',scale: 10},"position": {"epoch": date.toISOString(),"cartographicDegrees": customMarks}});} else {console.error('无法从 ISO 8601 字符串解析日期');}}}}//清除上次数据props.viewer.dataSources.remove(obj);obj = null;//加载本次疏散czmlprops.viewer.dataSources.add(Cesium.CzmlDataSource.load(czml)).then(function (loadedDataSource) {obj = loadedDataSource;var entities = loadedDataSource.entities.values;for (var i = 0; i < entities.length; i++) {var s = entities[i];s.orientation = new Cesium.VelocityOrientationProperty(s.position);}})}onMounted(() => {
});onUnmounted(() => {//清除绘制的内容props.viewer.entities.removeAll();//绘制了火灾点切换的时候需要先清除if (firePrimitiveEntity.length) {for (const item of firePrimitiveEntity) {props.viewer.scene.primitives.remove(item);}}//绘制了多个火灾点并保存到了列表上离开时清除for (const iterator of listEntities) {for (const item of iterator.firePrimitiveEntity) {props.viewer.scene.primitives.remove(item);}}if (obj) {props.viewer.dataSources.remove(obj);obj = null;}});
</script><style scoped>
.page {position: absolute;right: 10px;top: 10px;color: #fff;background: #fff;padding: 10px;border-radius: 5px;width: 400px;
}
</style>

相关文章:

【Cesium开发实战】火灾疏散功能的实现,可设置火源点、疏散路径、疏散人数

Cesium有很多很强大的功能&#xff0c;可以在地球上实现很多炫酷的3D效果。今天给大家分享一个可自定义的火灾疏散人群的功能。 1.话不多说&#xff0c;先展示 火灾疏散模拟 2.设计思路 根据项目需求要求&#xff0c;可设置火源点、绘制逃生路线、可设置逃生人数。所以点击火…...

imx6ull/linux应用编程学习(16)emqx ,mqtt创建连接mqtt.fx

在很多项目中都需要自己的私人服务器&#xff0c;以保证数据的隐私性&#xff0c;这里我用的是emqx。 1.进入emqx官网 EMQX&#xff1a;用于物联网、车联网和工业物联网的企业级 MQTT 平台 点击试用cloud 申请成功后可得&#xff1a;&#xff08;右边的忽略&#xff09; 进入…...

Debezium系列之:验证mysql、mariadb等兼容mysql协议数据库账号权限

Debezium系列之:验证mysql、mariadb等兼容mysql协议数据库账号权限 一、数据库需要开启binlog二、创建账号和账号需要赋予的权限三、账号具有权限查看日志信息四、验证账号权限五、验证账号能否执行show master status六、验证数据库是否开启binlog一、数据库需要开启binlog …...

Vue.js学习笔记(五)抽奖组件封装——转盘抽奖

基于VUE2转盘组件的开发 文章目录 基于VUE2转盘组件的开发前言一、开发步骤1.组件布局2.布局样式3.数据准备 二、最后效果总结 前言 因为之前的转盘功能是图片做的&#xff0c;每次活动更新都要重做UI和前端&#xff0c;为了解决这一问题进行动态配置转盘组件开发&#xff0c;…...

使用pip或conda离线下载安装包,使用pip或conda安装离线安装包

使用pip或conda离线下载安装包&#xff0c;使用pip或conda安装离线安装包 一、使用pip离线下载安装包1. 在有网络的机器上下载包和依赖2. 传输离线安装包 二、在目标机器上离线安装pip包三、使用conda离线下载安装包1. 在有网络的机器上下载conda包2. 传输conda包或环境包3. 在…...

产品访问分析

1、DWD产品访问明细 1.1、用户产品权限数据 --用户产品权限数据INSERT OVERWRITE TABLE temp_lms.dm_lms_platform_usergroup_app_tmpselect 仓储司南 as pro_name,CCSN as pro_code,c.user_name as user_name,d.account_name …...

【算法】代码随想录之链表(更新中)

文章目录 前言 一、移除链表元素&#xff08;LeetCode--203&#xff09; 前言 跟随代码随想录&#xff0c;学习链表相关的算法题目&#xff0c;记录学习过程中的tips。 一、移除链表元素&#xff08;LeetCode--203&#xff09; 【1】题目描述&#xff1a; 【2】解决思想&am…...

react 18中,使用useRef 获取其他组件的dom并操作节点,flushSync强制同步更新useState

React 不允许组件访问其他组件的 DOM 节点。甚至自己的子组件也不行&#xff01;这是故意的。Refs 是一种脱围机制&#xff0c;应该谨慎使用。手动操作 另一个 组件的 DOM 节点会使你的代码更加脆弱。 相反&#xff0c;想要 暴露其 DOM 节点的组件必须选择该行为。一个组件可以…...

Jupyter Notebook基础:用IPython实现动态编程

Jupyter Notebook基础&#xff1a;用IPython实现动态编程 1. 引言 Jupyter Notebook是一个基于Web的交互式计算环境&#xff0c;允许用户创建和共享包含实时代码、方程式、可视化和文本叙述的文档。它广泛应用于数据清洗与转换、数值模拟、统计建模、机器学习以及其他数据科学…...

Python 爬虫:使用打码平台来识别各种验证码:

本课程使用的是 超级鹰 打码平台&#xff0c; 没有账户的请自行注册&#xff01; 超级鹰验证码识别-专业的验证码云端识别服务,让验证码识别更快速、更准确、更强大 使用打码平台来攻破验证码难题&#xff0c; 是很简单容易的&#xff0c; 但是要钱&#xff01; 案例代码及测…...

理解算法复杂度:空间复杂度详解

引言 在计算机科学中&#xff0c;算法复杂度是衡量算法效率的重要指标。时间复杂度和空间复杂度是算法复杂度的两个主要方面。在这篇博客中&#xff0c;我们将深入探讨空间复杂度&#xff0c;了解其定义、常见类型以及如何进行分析。空间复杂度是衡量算法在执行过程中所需内存…...

浅析Kafka Streams消息流式处理流程及原理

以下结合案例&#xff1a;统计消息中单词出现次数&#xff0c;来测试并说明kafka消息流式处理的执行流程 Maven依赖 <dependencies><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-streams</artifactId><exclusio…...

QGroundControl的总体架构,模块化设计和主要组件的功能。

QGroundControl 总体架构详细描述 QGroundControl (QGC) 作为一个开源地面控制站软件&#xff0c;其设计原则是模块化、高扩展性和高可维护性。 总体架构 QGroundControl 由多个层次构成&#xff0c;每个层次负责不同的功能。这种分层结构确保了系统的高内聚性和低耦合性。 …...

oracle 表空间文件迁移

表空间文件迁移 背景 由于各种原因&#xff0c;在实际工作中可能会出现oracle服务器数据盘空间被占满的情况&#xff0c;这个时候单纯的添加新磁盘&#xff0c;后续表空间文件放新盘的方案已经不适用了&#xff0c;因为源盘已经占用满了&#xff0c;数据库服务会异常&#xf…...

JVM学习(day1)

JVM 运行时数据区 线程共享&#xff1a;方法区、堆 线程独享&#xff08;与个体“同生共死”&#xff09;&#xff1a;虚拟机栈、本地方法栈、程序计数器 程序计数器 作用&#xff1a;记录下次要执行的代码行的行号 特点&#xff1a;为一个没有OOM&#xff08;内存溢出&a…...

js项目生产环境中移除 console

1、terser-webpack-plugin webpack 构建的项目中安装使用 安装&#xff1a; npm install terser-webpack-plugin --save-dev 配置 在webpack.config.js文件中 new TerserPlugin({terserOptions: {output: {comments: false, // 去除注释},warnings: false, // 去除黄色警告,co…...

ROS2 + 科大讯飞 初步实现机器人语音控制

环境配置&#xff1a; 电脑端&#xff1a; ubuntu22.04实体机作为上位机 ROS版本&#xff1a;ros2-humble 实体机器人&#xff1a; STM32 思岚A1激光雷达 科大讯飞语音SDK 讯飞开放平台-以语音交互为核心的人工智能开放平台 实现步骤&#xff1a; 1. 下载和处理科大讯飞语音模…...

HTML5新增的input元素属性:placeholder、required、autofocus、min、max等

HTML5 大幅度地增加与改良了 input 元素的属性&#xff0c;可以简单地使用这些属性来实现 HTML5 之前需要使用 JavaScript 才能实现的许多功能。 下面将详细介绍这些新增的 input 元素的属性。 属性说明属性说明placeholder在输入框显示描述性或提示性文本autocomplete是否保…...

Cornerstone3D导致浏览器崩溃的踩坑记录

WebGL: CONTEXT_LOST_WEBGL: loseContext: context lost ⛳️ 问题描述 在使用vue3vite重构Cornerstone相关项目后&#xff0c;在Mac本地运行良好&#xff0c;但是部署测试环境后&#xff0c;在window系统的Chrome浏览器中切换页面会导致页面崩溃。查看Chrome的任务管理器&am…...

【鸿蒙学习笔记】Stage模型

官方文档&#xff1a;Stage模型开发概述 目录标题 Stage模型好处Stage模型概念图ContextAbilityStageUIAbility组件和ExtensionAbility组件WindowStage Stage模型-组件模型Stage模型-进程模型Stage模型-ArkTS线程模型和任务模型关于任务模型&#xff0c;我们先来了解一下什么是…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用

前言&#xff1a;我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM&#xff08;Java Virtual Machine&#xff09;让"一次编写&#xff0c;到处运行"成为可能。这个软件层面的虚拟化让我着迷&#xff0c;但直到后来接触VMware和Doc…...

海云安高敏捷信创白盒SCAP入选《中国网络安全细分领域产品名录》

近日&#xff0c;嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》&#xff0c;海云安高敏捷信创白盒&#xff08;SCAP&#xff09;成功入选软件供应链安全领域产品名录。 在数字化转型加速的今天&#xff0c;网络安全已成为企业生存与发展的核心基石&#xff0c;为了解…...