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,};}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/110155.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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

文章目录 一、log4j2二、背景三、影响版本四、漏洞原理五、LDAP和JNDI是什么六、漏洞手工复现1、利用DNSlog来测试漏洞是否存在2、加载恶意文件Exploit.java&#xff0c;将其编译成class文件3、开启web服务4、在恶意文件Exploit.class所在的目录开启LDAP服务5、监听反弹shell的…

SEO优化排名的技巧与注意点(百度SEO排名的五大注意点)

关键词排名是指在搜索引擎中&#xff0c;用户搜索相关关键词时&#xff0c;网站出现的顺序。SEO优化是提高网站排名的一种方法。优化关键词排名的目的是提高网站流量和知名度。但是要注意遵循百度SEO排名的规则。 下面介绍一下百度SEO排名的五大注意点和优化关键词的六种方式。…

如何实现一个简单的Promise/A+规范的Promise库?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ Promise/A规范的Promise⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚…

去除pdf/word的水印艺术字

对于pdf中的水印如果无法去除水印&#xff0c;则先另存为word&#xff0c;然后再按下面办法处理即可&#xff1a; 查看宏&#xff0c;创建&#xff1a;删除艺术字 添加内容&#xff1a; Sub 删除艺术字()Dim sh As ShapeFor Each sh In ActiveDocument.ShapesIf sh.Type msoT…

第二节:利用VBA代码交换三个单元格的值

【分享成果&#xff0c;随喜正能量】经常在做一件事时&#xff0c;一开始动力很足&#xff0c;可时间久了&#xff0c;就会出现意志力消耗殆尽。流水不腐&#xff0c;户枢不蠹。做一件对自己好的小事&#xff0c;养一个好习惯&#xff0c;慢慢坚持&#xff0c;持续去做&#xf…

HAProxy终结TLS双向认证代理EMQX集群

文章目录 1. 背景介绍2. 系统架构3. 证书签发3.1 创建根证书3.2 创建中间证书3.3 创建设备证书3.4 创建服务端证书 4. HAProxy开启双向认证5. 验证6. 总结 1. 背景介绍 MQTT协议已经成为当前物联网领域的关键技术之一&#xff0c;当前市面上主流的实现MQTT协议的产品主要有 EMQ…

【微服务】六. Nacos配置管理

6.1 Nacos实现配置管理 配置更改热更新 在nacos左侧新建配置管理 Data ID&#xff1a;就是配置文件名称 一般命名规则&#xff1a;服务名称-环境名称.yaml 配置内容填写&#xff1a;需要热更新需求的配置 配置文件的id&#xff1a;[服务名称]-[profile].[后缀名] 分组&#…

CSS:实现文字溢出显示省略号且悬浮显示tooltip完整信息

组件&#xff1a; element ui中的tooltip组件 思路&#xff1a;通过ref获取宽度进行判断&#xff0c;当子级宽度大于对应标签/父级宽度显示tooltip组件 <div class"bechmark-wrap"><ul ref"bechmarkUl"><liv-for"(item,index) in comp…

python科研作图

1、气泡图 气泡图是一种在xy轴上显示三个维度的数据的有效方式。在气泡图中&#xff0c;基本上&#xff0c;每个气泡代表一个数据点。横坐标和纵坐标的位置代表两个维度&#xff0c;气泡的大小则代表第三个维度。 在这个例子中&#xff0c;我们用numpy库生成了一些随机数据&a…

软件测试常问面试题

1、讲一下你最熟悉的模块是怎么测试的&#xff1f; 2、fiddler如何抓https请求&#xff1f; 步骤&#xff1a; 设置浏览器http代理 安装证书 导入证书&#xff0c;端口号8888 手机端获取fiddler的地址&#xff0c;配置无线局域网代理&#xff0c;安装手机证书。 3、jmeter如何参…

【C# Programming】继承、接口

一、继承 1、派生 继承在相似而又不同的概念之间建立了类层次概念。 更一般的类称为基类&#xff0c;更具体的类称为派生类。派生类继承了基类的所有性质。 定义派生类要在类标识符后面添加一个冒号&#xff0c;接着添加基类名。 public class PdaItem {public string Name {…

【Spring Boot系列】- Spring Boot侦听器Listener

【Spring Boot系列】- Spring Boot侦听器Listener 文章目录 【Spring Boot系列】- Spring Boot侦听器Listener一、概述二、监听器Listener分类2.1 监听ServletContext的事件监听器2.2 监听HttpSeesion的事件监听器2.3 监听ServletRequest的事件监听器 三、SpringMVC中的监听器3…