IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Cesium 三维管道网络模拟 -> 正文阅读

[JavaScript知识库]Cesium 三维管道网络模拟

Cesium 管道实体

  • 目的在于根据数据的点坐标生成三维管网

  • 分为水平管道与垂直管道两类,在两类管道接洽时避免了重叠现象的出现

  • 使用es5对象思维进行封装

使用方法

垂直管道

VerticalPipe(pipeEntityCollection, id, positions, height, pipeRadius, pipeHeight, waterHeight)

参数解释

param {DataSource} pipeEntityCollection: 添加实体的数据源(viewer或自定义CustomDataSource)

param {String} id: 实体id

param {Array} positions: 实体经纬度 [经度, 纬度]

param {Number} height: 实体据地面高度,默认为0

param {Number} pipeRadius: 管道外径,默认外径0.8、内径为外径的2/3

param {Number} pipeHeight: 管道高度, 默认为1.5

param {Number} waterHeight: 管道内水高, 默认为0


水平管道

HorizontalPipe(pipeEntityCollection, id, positions, cut, status, pipeRadius)

参数解释

param {DataSource} pipeEntityCollection: 添加实体的数据源(viewer或自定义CustomDataSource)

param {String} id: 实体id

param {Array} positions: 组成管道的点集合 […, 经度, 纬度, 高度, …]

param {"single" | "both" | "null"} cut: 为避免水平管道与垂直管道重叠对水平管道进行裁切,默认不裁切

param {1 | 2 | 3 | 4} status: 管道内水位状态, 默认为1

param {Number} pipeRadius: 管道外径,默认为0.4、内径为外径的2/3

实际演示

生成两个垂直管道,中间由一段水平管道相连,代码与实际结果如下:

// 垂直管道
VerticalPipe(pipeEntityCollection, "node-A", [117.145668, 34.2198067], 0, null, null, 0.8);
VerticalPipe(pipeEntityCollection, "node-B", [117.1459503, 34.2195511], 0, null, null, 0.8);
// 水平管道
HorizontalPipe(
  pipeEntityCollection,
  "link",
  [
    117.1456680, 34.2198067, 0, 
    117.1457386, 34.2197631, 0, 
    117.1458055, 34.2197096, 0,
    117.1458516, 34.2196686, 0, 
    117.1459059, 34.2196069, 0, 
    117.1459503,34.21955110, 0
  ],
 	"both",
  2
);

可以看到,虽然垂直管道与水平管道有坐标点重叠,但是展示时两者并无叠置


源码解析

源码下载地址:Cesium垂直+水平含水管道实体-Javascript文档类资源-CSDN文库

大部分代码都是很简单的逻辑,大家自行查看源码即可,这里重点讲解两部分代码

  1. 根据中心点和半径生成圆形的函数
	/**
	 * 管道截面形状计算,根据中心点和半径生成圆形
	 * @param {Array} initialPosition [经度, 纬度]
	 * @param {Number} radius 截面半径
	 * @returns 组成截面的点集合
	 */
	function computeCircle(initialPosition, radius) {
		let Ea = 6378137; //   赤道半径
		let Eb = 6356725; // 极半径
		let positionArr = [];
		//cesium正东是0°
		for (let i = 0; i <= 360; i++) {
			let dx = radius * Math.sin((i * Math.PI) / 180.0);
			let dy = radius * Math.cos((i * Math.PI) / 180.0);

			let ec = Eb + ((Ea - Eb) * (90.0 - initialPosition[1])) / 90.0;
			let ed = ec * Math.cos((initialPosition[1] * Math.PI) / 180);

			let BJD = initialPosition[0] + ((dx / ed) * 180.0) / Math.PI; // 圆弧点经度
			let BWD = initialPosition[1] + ((dy / ec) * 180.0) / Math.PI; // 圆弧点纬度

			positionArr.push(BJD);
			positionArr.push(BWD);
		}
		return positionArr;
	}

关于这段代码可以参照此文,这位大佬写的很好通过经纬度坐标计算距离的方法(经纬度距离计算)ZZ_躬行之的技术博客_51CTO博客

其中dx、dy为根据半径计算出的x、y偏移量

ec为地球中心到当前纬度的半径

initialPosition[1] * Math.PI) / 180是将纬度转换为弧度

而ed则是当前纬度圈的半径

dx/ed、dy/ec为经度和纬度变化值对应的弧度

BJD、BWD则为初始经纬度+变化经纬度=变化后的经纬度

  1. 对水平管道进行裁切的函数
  /**
	 * 避免水平管道与垂直管道重叠,重新计算初末位置
	 * @param {"pipe" | "water"} type  管道或者水体
	 * @param {"single" | "both" | "null"} cut 单侧裁切、两侧裁切、不裁切
	 * @returns {Array} cartesianPositions
	 */
	function computePos(type, cut) {
		let waterPositions = positions.concat();
		let cartesianPositions;
		if (type == "water") {
			for (let i = 2; i < waterPositions.length; i += 3) {
				waterPositions[i] += 0.4 - 0.25;
			}
			cartesianPositions = new Cesium.Cartesian3.fromDegreesArrayHeights(waterPositions);
		} else if (type == "pipe") {
			cartesianPositions = new Cesium.Cartesian3.fromDegreesArrayHeights(positions);
		}
		const start = cartesianPositions[0];
		const second = cartesianPositions[1];
		const end = cartesianPositions[cartesianPositions.length - 1];
		const secondToLast = cartesianPositions[cartesianPositions.length - 2];
		const startLength = Math.sqrt(Math.pow(start.x - second.x, 2) + Math.pow(start.y - second.y, 2) + Math.pow(start.z - second.z, 2));
		const endLength = Math.sqrt(Math.pow(secondToLast.x - end.x, 2) + Math.pow(secondToLast.y - end.y, 2) + Math.pow(secondToLast.z - end.z, 2));
		const startOffsetX = (0.7 / startLength) * (second.x - start.x);
		const startOffsetY = (0.7 / startLength) * (second.y - start.y);
		const startOffsetZ = (0.7 / startLength) * (second.z - start.z);
		const endOffsetX = (0.7 / endLength) * (secondToLast.x - end.x);
		const endOffsetY = (0.7 / endLength) * (secondToLast.y - end.y);
		const endOffsetZ = (0.7 / endLength) * (secondToLast.z - end.z);

		if (cut == "single") {
			start.x += startOffsetX;
			start.y += startOffsetY;
			start.z += startOffsetZ;
		}
		if (cut == "both") {
			start.x += startOffsetX;
			start.y += startOffsetY;
			start.z += startOffsetZ;
			end.x += endOffsetX;
			end.y += endOffsetY;
			end.z += endOffsetZ;
		}

		return cartesianPositions;
	}

这段代码相较于上一部分则容易理解的多,核心思想为空间中的相似三角形

startLength、endLength分别为多段管道中的第一段和最后一段

start、end分别为初始点和终点

公式原理如图所示

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-07 11:06:01  更:2022-05-07 11:06:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:14:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码