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

Cesium 地球网格构造

Cesium 地球网格构造

Cesium原理篇:3最长的一帧之地形(2:高度图)

请添加图片描述

HeightmapTessellator

用于从高程图像创建网格。提供了一个函数 computeVertices,可以根据高程图像创建顶点数组。

该函数的参数包括高程图像、高度数据的结构、网格宽高、边缘裙板高度、矩形范围、相机中心点等。函数的实现使用了许多性能优化技巧,如将函数内常量化、内联等。

该模块的输出为一个对象,包括创建好的顶点数组、最大与最小高度、该网格的边界球、边界方向盒等信息。

1、函数定义

// 声明
static computeVertices(options) {}
// 使用
const width = 5;
const height = 5;
const statistics = Cesium.HeightmapTessellator.computeVertices({heightmap : [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],width : width,height : height,skirtHeight : 0.0,nativeRectangle : {west : 10.0,east : 20.0,south : 30.0,north : 40.0}
});const encoding = statistics.encoding;
const position = encoding.decodePosition(statistics.vertices, index);

options 参数:

参数类型描述
heightmapArray要镶嵌的高度图。
widthnumber高度图的宽度(以高度样本计)。
heightnumber高度图的高度(以高度样本计)。
skirtHeightnumber要悬垂在高度图边缘的裙子的高度。
nativeRectangleRectangle高度贴图投影的原始坐标中的矩形。对于具有地理投影的高度图,这是度数。对于 Web 墨卡托投影,这是米。
exaggerationnumber用于夸大地形的比例尺。默认为1.
exaggerationRelativeHeightnumber地形夸大的高度,以米为单位。默认为0.
rectangleRectangle高度图覆盖的矩形,大地坐标为北、南、东和西属性(弧度)。必须提供矩形或本机矩形。如果同时提供两者,则假定它们是一致的。
isGeographicboolean如果高度图使用{@link GeographicProjection},则为true;如果使用{@link WebMercatorProjection},则为false。默认为true。
relativeToCenterCartesian3将计算出的位置作为Cartesian3.subtract(worldPosition, relativeToCenter)。默认为Cartesian3.ZERO。
ellipsoidEllipsoid高度贴图适用的椭球体。默认为Ellipsoid.WGS84。
structureobject描述高度数据结构的对象。

裙边(skirt)

防止不同层级mesh加载时出现裂缝

实现

  static computeVertices(options) {const cos = Math.cos;const sin = Math.sin;const sqrt = Math.sqrt;const toRadians = CesiumMath.toRadians;const heightmap = options.heightmap;const width = options.width;const height = options.height;const skirtHeight = options.skirtHeight;const hasSkirts = skirtHeight > 0.0;const ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);const nativeRectangle = Rectangle.clone(options.nativeRectangle);const rectangle = Rectangle.clone(options.rectangle);const geographicWest = rectangle.west;const geographicSouth = rectangle.south;const geographicEast = rectangle.east;const geographicNorth = rectangle.north;const relativeToCenter = options.relativeToCenter;const includeWebMercatorT = defaultValue(options.includeWebMercatorT, false);const exaggeration = defaultValue(options.exaggeration, 1.0);const exaggerationRelativeHeight = defaultValue(options.exaggerationRelativeHeight,0.0);const hasExaggeration = exaggeration !== 1.0;const includeGeodeticSurfaceNormals = hasExaggeration;const rectangleWidth = Rectangle.computeWidth(nativeRectangle);const rectangleHeight = Rectangle.computeHeight(nativeRectangle);// 每个网格的长宽const granularityX = rectangleWidth / (width - 1);const granularityY = rectangleHeight / (height - 1);const radiiSquared = ellipsoid.radiiSquared;const radiiSquaredX = radiiSquared.x;const radiiSquaredY = radiiSquared.y;const radiiSquaredZ = radiiSquared.z;let minimumHeight = 65536.0;let maximumHeight = -65536.0;const fromENU = Transforms.eastNorthUpToFixedFrame(relativeToCenter,ellipsoid);const minimum = minimumScratch;minimum.x = Number.POSITIVE_INFINITY;minimum.y = Number.POSITIVE_INFINITY;minimum.z = Number.POSITIVE_INFINITY;const maximum = maximumScratch;maximum.x = Number.NEGATIVE_INFINITY;maximum.y = Number.NEGATIVE_INFINITY;maximum.z = Number.NEGATIVE_INFINITY;let hMin = Number.POSITIVE_INFINITY;const gridVertexCount = width * height;const edgeVertexCount = skirtHeight > 0.0 ? width * 2 + height * 2 : 0;const vertexCount = gridVertexCount + edgeVertexCount;const positions = new Array(vertexCount);const heights = new Array(vertexCount);const uvs = new Array(vertexCount);let startRow = 0;let endRow = height;let startCol = 0;let endCol = width;if (hasSkirts) {--startRow;++endRow;--startCol;++endCol;}for (let rowIndex = startRow; rowIndex < endRow; ++rowIndex) {let row = rowIndex;if (row < 0) {row = 0;}if (row >= height) {row = height - 1;}////  ^ latitude(纬度)//  |//  |              North(90)//  |              ---------//  |             |         |//  |  West(-180) |         | East(0)//  |             |         |//  |              ---------//  |              South(-90)//  -----------------------------> longitude(经度)// 地理坐标系下// 当前纬度(latitude) 距离最北头(North) 的距离// 这个值是越来越小的, 随着行数越来越大let latitude = nativeRectangle.north - granularityY * row;latitude = toRadians(latitude);// 当前纬度(latitude) 距离最南头(South) 的百分比(0~1)let v = (latitude - geographicSouth) / (geographicNorth - geographicSouth);v = CesiumMath.clamp(v, 0.0, 1.0);const isNorthEdge = rowIndex === startRow;const isSouthEdge = rowIndex === endRow - 1;const cosLatitude = cos(latitude);const nZ = sin(latitude);const kZ = radiiSquaredZ * nZ;for (let colIndex = startCol; colIndex < endCol; ++colIndex) {let col = colIndex;if (col < 0) {col = 0;}if (col >= width) {col = width - 1;}const terrainOffset = row * width + col;let heightSample = heightmap[terrainOffset]let longitude = nativeRectangle.west + granularityX * col;longitude = toRadians(longitude);let u = (longitude - geographicWest) / (geographicEast - geographicWest);u = CesiumMath.clamp(u, 0.0, 1.0);let index = row * width + col;if (skirtHeight > 0.0) {const isWestEdge = colIndex === startCol;const isEastEdge = colIndex === endCol - 1;const isEdge = isNorthEdge || isSouthEdge || isWestEdge || isEastEdge;const isCorner = (isNorthEdge || isSouthEdge) && (isWestEdge || isEastEdge);if (isCorner) {// Don't generate skirts on the corners.continue;} else if (isEdge) {heightSample -= skirtHeight;if (isWestEdge) {// The outer loop iterates north to south but the indices are ordered south to north, hence the index flip below// 外循环从北到南迭代,但索引按从南到北的顺序排列,因此索引在下面翻转index = gridVertexCount + (height - row - 1);} else if (isSouthEdge) {// Add after west indices. South indices are ordered east to west.// 加在西方指数之后。南方指数是从东向西排列的。index = gridVertexCount + height + (width - col - 1);} else if (isEastEdge) {// Add after west and south indices. East indices are ordered north to south. The index is flipped like above.// 在西部和南部指数后加上。东部指数是从北向南排列的。索引如上所述翻转。index = gridVertexCount + height + width + row;} else if (isNorthEdge) {// Add after west, south, and east indices. North indices are ordered west to east.// 在西部、南部和东部指数后添加。北方指数是从西向东排列的。index = gridVertexCount + height + width + height + col;}}}// 经纬度转笛卡尔坐标系const nX = cosLatitude * cos(longitude);const nY = cosLatitude * sin(longitude);const kX = radiiSquaredX * nX;const kY = radiiSquaredY * nY;const gamma = sqrt(kX * nX + kY * nY + kZ * nZ);const oneOverGamma = 1.0 / gamma;const rSurfaceX = kX * oneOverGamma;const rSurfaceY = kY * oneOverGamma;const rSurfaceZ = kZ * oneOverGamma;const position = new Cartesian3();position.x = rSurfaceX + nX * heightSample;position.y = rSurfaceY + nY * heightSample;position.z = rSurfaceZ + nZ * heightSample;hMin = Math.min(hMin, heightSample);positions[index] = position;uvs[index] = new Cartesian2(u, v);heights[index] = heightSample;}}const aaBox = new AxisAlignedBoundingBox(minimum, maximum, relativeToCenter);const encoding = new TerrainEncoding(relativeToCenter,aaBox,hMin,maximumHeight,fromENU,false,includeWebMercatorT,includeGeodeticSurfaceNormals,exaggeration,exaggerationRelativeHeight);const vertices = new Float32Array(vertexCount * encoding.stride);let bufferIndex = 0;for (let j = 0; j < vertexCount; ++j) {bufferIndex = encoding.encode(vertices,bufferIndex,positions[j],uvs[j],heights[j],undefined,undefined,undefined);}return {vertices: vertices,};}

相关文章:

Cesium 地球网格构造

Cesium 地球网格构造 Cesium原理篇&#xff1a;3最长的一帧之地形(2&#xff1a;高度图) HeightmapTessellator 用于从高程图像创建网格。提供了一个函数 computeVertices&#xff0c;可以根据高程图像创建顶点数组。 该函数的参数包括高程图像、高度数据的结构、网格宽高、…...

C++深度优化——cacheline测试

cacheline是内存调度的基本结构&#xff0c;其大小一般为32B或者64B。关于本机具体的配置信息可以在配置文件中看到&#xff1a; 这里可以看到我的这台机器的cacheline大小是64B。对于cacheline在多核处理器中有一个伪共享的状态&#xff0c;具体可以参考以下博客&#xff1a;高…...

【数字IC/FPGA】Verilog中的递归调用

参考文章 在Verilog2001中,模块的递归调用是可能的,引用下面的一段话(出自上面的参考文章) Many designers think that recursive techniques cannot be applied to hardware design. I’m not really sure where this misconception comes from. While it is true that i…...

禁用Win10自动更新

第一步&#xff0c;winr&#xff0c;输入 gpedit.msc 并回车&#xff0c;打开【组策略】 第二步&#xff0c;依次点击 管理模板->Windows组件->Windows更新 第三步&#xff0c;双击Windows更新&#xff0c;然后在设置中双击 指定 intranet Microsoft 更新服务位置 第…...

算法通关村-----动态规划高频问题

最少硬币数问题 问题描述 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1 。你可以认为每种硬…...

记一起小意外事件引起的批量重命名文件名

一、事件描述 某次,因某业务系统迁移,一线人员对业务目录误操作,执行打包命令过程中导致Tomcat下的web应用程序无法使用,检查后发现项目下所有文件名都加了gz格式;询问一线,发现是对项目目录执行了:gzip -r ./tomcat导致程序文件找不到;报错如下: 二、事件处理 1、查看…...

【Excel函数】Excel的Len函数求对象的字符数

在Excel中&#xff0c;LEN函数用于计算文本字符串中的字符数。它的语法如下。 LEN(text) 其中&#xff0c;text是要计算字符数的文本字符串。 例如&#xff0c;如果你想计算单元格A1中文本的字符数&#xff0c;可以使用以下公式&#xff1a; A2len(a1) 结果将返回单元格A1中文…...

小白备战大厂算法笔试(八)——搜索

搜索 二分查找 二分查找是一种基于分治策略的高效搜索算法。它利用数据的有序性&#xff0c;每轮减少一半搜索范围&#xff0c;直至找到目标元素或搜索区间为空为止。 Question&#xff1a; 给定一个长度为n的数组 nums &#xff0c;元素按从小到大的顺序排列&#xff0c;数组…...

〔022〕Stable Diffusion 之 生成视频 篇

✨ 目录 &#x1f388; 视频转换 / mov2mov&#x1f388; 视频转换前奏准备&#x1f388; 视频转换 mov2mov 使用&#x1f388; 视频转换 mov2mov 效果预览&#x1f388; 视频无限缩放 / Infinite Zoom&#x1f388; 视频无限缩放 Infinite Zoom 使用 &#x1f388; 视频转换 /…...

网络安全深入学习第三课——热门框架漏洞(RCE—Struts2远程代码执行)

文章目录 一、Struts2框架介绍二、Struts2远程代码执行漏洞三、Struts2执行代码的原理四、Struts2框架特征五、漏洞手工POC六、漏洞工具复现 一、Struts2框架介绍 ------ Struts2是apache项目下的一个web 框架&#xff0c;普遍应用于阿里巴巴、京东等互联网、政府、企业门户网…...

【uni-app】

准备工作&#xff08;Hbuilder&#xff09; 1.下载hbuilder&#xff0c;插件使用Vue3的uni-app项目 2.需要安装编译器 3.下载微信开发者工具 4.点击运行->微信开发者工具 5.打开微信开发者工具的服务端口 效果图 准备工作&#xff08;VScode&#xff09; 插件 uni-cr…...

Pytorch 多卡并行(3)—— 使用 DDP 加速 minGPT 训练

前文 并行原理简介和 DDP 并行实践 和 使用 torchrun 进行容错处理 在简单的随机数据上演示了使用 DDP 并行加速训练的方法&#xff0c;本文考虑一个更加复杂的 GPT 类模型&#xff0c;说明如何进行 DDP 并行实战MinGPT 是 GPT 模型的一个流行的开源 PyTorch 复现项目&#xff…...

IAM、EIAM、CIAM、RAM、IDaaS 都是什么?

后端程序员在做 ToB 产品或者后台系统时&#xff0c;都不可避免的会遇到账号系统、登录系统、权限系统、日志系统等这些核心功能。这些功能一般都是以 SSO 系统、RBAC 权限管理系统等方式命名&#xff0c;但这些系统合起来有一个专有名词&#xff1a;IAM。 IAM IAM 是 Identi…...

STM32 Cubemx 通用定时器 General-Purpose Timers同步

文章目录 前言简介cubemx配置 前言 持续学习stm32中… 简介 通用定时器是一个16位的计数器&#xff0c;支持向上up、向下down与中心对称up-down三种模式。可以用于测量信号脉宽&#xff08;输入捕捉&#xff09;&#xff0c;输出一定的波形&#xff08;比较输出与PWM输出&am…...

Ubuntu 20.04降级clang-format

1. 卸载clang-format sudo apt purge clang-format 2. 安装clang-format-6.0 sudo apt install clang-format-6.0 3. 软链接clang-format sudo ln -s /usr/bin/clang-format-6.0 /usr/bin/clang-format...

激活函数总结(三十四):激活函数补充(FReLU、CReLU)

激活函数总结&#xff08;三十四&#xff09;&#xff1a;激活函数补充 1 引言2 激活函数2.1 FReLU激活函数2.2 CReLU激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函数 (Sigmoid、Tanh、ReLU、Leaky ReLU、PReLU、Swish、ELU、SELU、GELU、Softmax、Sof…...

【LeetCode-简单题KMP】459. 重复的子字符串

文章目录 题目方法一&#xff1a;移动匹配方法二&#xff1a;KMP算法 题目 方法一&#xff1a;移动匹配 class Solution {//移动匹配public boolean repeatedSubstringPattern(String s) {StringBuffer str new StringBuffer(s);//ababstr.append(s);//拼接一份自己 abababab…...

Lua脚本

基本语法 注释 print(“script lua win”) – 单行注释 – [[ 多行注释 ]] – 标识符 类似于&#xff1a;java当中 变量、属性名、方法名。 以字母&#xff08;a-z,A-Z&#xff09;、下划线 开头&#xff0c;后面加上0个或多个 字母、下划线、数字。 不要用下划线大写字母…...

vue 封装一个Dialog组件

基于element-plus封装一个Dialog组件 <template><section class"dialog-wrap"><el-dialog :title"title" v-model"visible" :close-on-click-modal"false"><section class"content-wrap"><Form…...

外包干了2个月,技术退步明显。。。。。

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...

Python爬虫实战:构建智能职位信息聚合工具JobClaw

1. 项目概述&#xff1a;一个面向开发者的智能职位信息聚合与解析工具最近在帮团队招聘和看机会的朋友聊天&#xff0c;发现一个挺普遍的问题&#xff1a;大家找技术岗位&#xff0c;要么在几个主流招聘App上反复刷&#xff0c;信息分散且格式不一&#xff1b;要么就是盯着几个…...

Windows 11任务栏拖放功能终极修复指南:3步恢复高效操作体验

Windows 11任务栏拖放功能终极修复指南&#xff1a;3步恢复高效操作体验 【免费下载链接】Windows11DragAndDropToTaskbarFix "Windows 11 Drag & Drop to the Taskbar (Fix)" fixes the missing "Drag & Drop to the Taskbar" support in Windows…...

2026年医疗卫生/护理求职AI工具横评:白衣天使的求职神器大比拼

导语 2026年&#xff0c;医疗卫生行业依然是最具社会价值和就业稳定性的行业之一。随着中国老龄化加速&#xff0c;医护人员需求持续扩大&#xff0c;仅公立医院护士岗位需求量就突破200万。然而&#xff0c;医护求职并不轻松&#xff1a;编制紧张、规培政策复杂、职称考试压力…...

AI模型评估实战:从原理到实践,用Evaliphy简化评测全流程

1. 项目概述&#xff1a;当AI测试遇上“简化”难题最近和几个做AI应用开发的朋友聊天&#xff0c;大家不约而同地提到了同一个痛点&#xff1a;模型效果评估太折腾了。这让我想起自己去年折腾一个文本分类项目时的经历——为了评估模型在几个不同测试集上的表现&#xff0c;我写…...

从灰度图到粉彩叙事,全程可复现:5个精准Prompt模板+3类LUT预设,零基础速产美术馆级Pastel印相

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;从灰度图到粉彩叙事&#xff1a;Pastel印相的美学本质与技术边界 Pastel印相并非简单的色彩叠加&#xff0c;而是一种基于人眼感知非线性响应与胶片化学特性的数字模拟范式。其核心在于将灰度图像的亮度…...

NHSE:5分钟掌握动物森友会存档编辑,打造你的完美岛屿

NHSE&#xff1a;5分钟掌握动物森友会存档编辑&#xff0c;打造你的完美岛屿 【免费下载链接】NHSE Animal Crossing: New Horizons save editor 项目地址: https://gitcode.com/gh_mirrors/nh/NHSE 你是否曾经为了收集某个稀有家具而花费数周时间&#xff1f;是否因为地…...

EMAC寄存器系统:网络诊断与性能优化的关键

1. EMAC寄存器系统概述以太网媒体访问控制器&#xff08;EMAC&#xff09;是现代网络设备中负责数据链路层操作的核心硬件模块。作为网络通信的"交通警察"&#xff0c;EMAC不仅负责以太网帧的收发调度&#xff0c;还通过精密的寄存器系统记录着网络通信的每一个关键细…...

ThunderAI:开源本地AI助手桌面应用部署与核心架构解析

1. 项目概述&#xff1a;一个开源的AI助手桌面应用 最近在GitHub上闲逛&#xff0c;发现了一个挺有意思的项目&#xff0c;叫“ThunderAI”。这名字听起来就挺带劲&#xff0c;对吧&#xff1f;点进去一看&#xff0c;是个用Python写的桌面应用程序&#xff0c;核心功能是把几个…...

使用 llama.cpp + MTP 分支实现 1.5 倍 Token 输出加速实战指南

使用 llama.cpp MTP 分支实现 1.5 倍 Token 输出加速实战指南 摘要&#xff1a;本文详细介绍如何通过 llama.cpp 的 MTP&#xff08;Multi-Token Prediction&#xff09;PR 分支&#xff0c;配合 Qwen3.6-27B-MTP GGUF 量化模型&#xff0c;实现推理时每秒输出 token 数量翻倍…...

高校食堂学生信息录入系统开发实战|从0到1搭建简易Web系统

大家好&#xff5e; 最近完成了一个适合高校课程作业、小型食堂管理使用的「大学食堂学生信息录入系统」&#xff0c;全程用纯前端技术实现&#xff0c;无需复杂后端环境&#xff0c;双击即可运行&#xff0c;今天就来分享一下开发全过程、功能细节和使用技巧&#xff0c;适合刚…...