当前位置: 首页 > 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;我们先来了解一下什么是…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...