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

产品让在Cesium中绘制迁徙线,把我00后的小同事给蚌埠住了~

大家好,我是日拱一卒的攻城师不浪,致力于技术与艺术的融合。这是2024年输出的第42/100篇文章。

前言

在3D开发过程中,迁徙线这个场景起到了举足轻重的作用。

迁徙线通过直观的动态展示方式,将复杂的空间流动数据形象化,有助于分析和理解空间关系与变化趋势,为决策提供参考。

例如:人口迁徙动向自然灾害响应人口疏散指挥等应急指挥,经济贸易路线演示,病情扩散路线等诸多场景,迁徙线都发挥了重要作用;

今天我们在Cesium中实现迁徙线的功能;

封装Class类

在Cesium中,我们一般使用JS的Class类进行场景大类的封装,这样做有几个好处:

  • 在前端的任何框架中都可使用,与vue或者react无关;

  • 使用方便,通过灵活的参数控制场景的定制化需求;

  • 代码独立,易于后期维护迭代;

构造函数

封装类,一般都会有一个固定参数viewer需要传入,viewer就是Cesium实例化后的场景实例;

剩下的场景参数,我们可以用一个对象options进行承接,代码如下:

constructor(viewer, options = {}) {this.viewer = viewer;this.options = options;
}

飞线效果的初始化

先分析一下飞线的形状,我们都知道它就是从一个中心点向四周进行扩散,所以入参需要有一个中心点centerPos以及需要扩散到相应位置的点,这里我们用一个数组otherPosArr, 如下:

let centerPos = [120.3642, 36.0668];
let otherPosArr = [[120.3644, 36.1117],[119.9393, 36.7814],[120.4206, 36.185],[120.5732, 36.1893],
];

然后就是飞线的其它参数,例如线的宽度,线的数量等,我们都可以支持通过参数灵活绘制;

还有,就是一条迁徙线是由2条线组成,一条固定的轨迹线,一条飞动的线,我们都可以选择entity去绘制,其中飞动的线需要自定义材质;

// 创建飞线
viewer.entities.add({id: `odLine_${index}_${i}`,polyline: {width,positions: _siglePositions,material: new LineFlowMaterialProperty({color: Color.fromAlpha(Color.AQUA, 0.8),speed: 8 * Math.random(),percent: 0.1,gradient: 0.01,}),},
});// 创建轨迹线
viewer.entities.add({id: `odLine_${index}`,polyline: {width,positions: _siglePositions,material: Color.fromAlpha(Color.AQUA, 0.3),},
})

自定义材质

自定义材质的glsl:

Material.LineFlowMaterialSource = `uniform vec4 color;uniform float speed;uniform float percent;uniform float gradient;czm_material czm_getMaterial(czm_materialInput materialInput){czm_material material = czm_getDefaultMaterial(materialInput);vec2 st = materialInput.st;float t =fract(czm_frameNumber * speed / 1000.0);t *= (1.0 + percent);float alpha = smoothstep(t- percent, t, st.s) * step(-t, -st.s);alpha += gradient;material.diffuse = color.rgb;material.alpha = alpha;return material;}`

抛物线算法

定义一个函数,通过抛物线方程计算从起点到终点的高度,生成一个抛物线形的坐标数组。

parabolaCalculate(startPosition, endPosition, height = 0, count = 50) {let result = [];height = Math.max(+height, 100);count = Math.max(+count, 50);let diffLon = Math.abs(startPosition[0] - endPosition[0]);let diffLat = Math.abs(startPosition[1] - endPosition[1]);let L = Math.max(diffLon, diffLat);let dlt = L / count;if (diffLon > diffLat) {let delLat = (endPosition[1] - startPosition[1]) / count;if (startPosition[0] - endPosition[0] > 0) {dlt = -dlt;}for (let i = 0; i < count; i++) {let h = height - (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * height) / Math.pow(L, 2);let lon = startPosition[0] + dlt * i;let lat = startPosition[1] + delLat * i;let point = new Cartesian3.fromDegrees(lon, lat, h);result.push(point);}}return result;
}

抛物线方程为

其中 h 是高度,L 是较大横纵间距。

  • diffLondiffLat 表示起始点和终点的经纬度差异,用来判断抛物线的方向。

  • 返回的 result 数组包含了 Cesium Cartesian3 格式的坐标点,用于构建飞行线的路径。

清除方法

可通过遍历 viewer.entities 中的实体,删除 idodLine_ 开头的实体,从而移除所有迁徙飞线和轨迹线。

clear() {const entities = this.viewer.entities.values;// 遍历并删除带有 'custom-line' 标识符的实体for (let i = entities.length - 1; i >= 0; i--) {if (entities[i].id && entities[i].id.startsWith("odLine_")) {this.viewer.entities.remove(entities[i]);}}
}

最后

以上就是Cesium中绘制迁徙线的核心代码,如果想系统学习Cesium,可以了解下作者的Cesium系列教程《Cesium从入门到实战》,将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,学完后直接上手做项目,+作者:brown_7778(备注来意)了解课程细节。

另外有需要进可视化&Webgis交流群可以加我:brown_7778(备注来意),也欢迎数字孪生可视化领域的交流合作。


http://www.mrgr.cn/news/65347.html

相关文章:

  • thrift rpc 四种类型的服务端的实现详细介绍
  • 查询引擎的演变之旅 | OceanBase原理解读
  • [vulnhub]DC: 1
  • el-table 滚动条重置 手动控制滚动条
  • C语言案例——青蛙跳台阶问题
  • YOLOv10改进策略【注意力机制篇】| ICLR2023 高效计算与全局局部信息融合的 Sea_Attention 模块(含PSA二次创新)
  • Swift 开发教程系列 - 第2章:Swift 基础语法
  • 基于STM32的智能手环设计
  • 学习记录:js算法(八十三):全排列
  • 表件数count使用总结
  • 新闻稿件管理:SpringBoot框架技术突破
  • Java复习32(PTA)
  • 【智能算法应用】鹈鹕优化算法求解二维路径规划问题
  • 布朗运动
  • 大数据挖掘有哪些技术要点?
  • Fork突然报错
  • 详解UDP协议
  • python-web开发神器:FastAPI详细使用(简单易用)
  • 一个小程序如何对接多个收款账户?
  • c++基础12比较/逻辑运算符
  • Python元组和列表在“用户信息管理”项目中的应用
  • VulkanTutorial(12·recreation swap chain,Vertex buffers)
  • SQLserver 表拆分
  • 从 vue 源码看问题 — 如何理解 vue 响应式?
  • Pyqt5蓝牙链接心跳检测
  • LeetCode 每日一题,用 Go 实现两数之和的非暴力解法