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

Cesium源码解析六(3dtiles属性获取、建筑物距离计算、建筑物着色及其原理分析)

快速导航

Cesium源码解析一(搭建开发环境)
Cesium源码解析二(terrain文件的加载、解析与渲染全过程梳理)
Cesium源码解析三(metadataAvailability的含义)
Cesium源码解析四(metadata元数据拓展中行列号的分块规则解析)
Cesium源码解析五(Quantized-Mesh(.terrain)格式文件在CesiumJS和UE中加载情况的对比)
Cesium源码解析六(3dtiles属性获取、建筑物距离计算、建筑物着色及其原理分析)

目录

  • 快速导航
  • 前言
  • 1.代码示例
  • 2.属性获取原理分析
  • 3.建筑物距离计算原理分析
  • 4.建筑物着色原理分析
  • 5.总结

前言

  在本文中,我们将探讨如何使用 CesiumJS 来加载和显示 3D 建筑物数据,并根据用户点击的位置进行动态着色。我们将使用 CesiumJS 的 OpenStreetMap 建筑物数据集,通过点击地图上的建筑物,根据距离计算并动态地为这些建筑物着色。这不仅增强了地图的交互性,还为用户提供了直观的地理空间数据可视化体验。我们将逐步讲解如何设置 Cesium Viewer,加载 3D 建筑物数据,处理用户点击事件,以及根据距离进行建筑物的颜色处理。希望通过本文,您能深入理解 CesiumJS 的强大功能,并能够在自己的项目中应用这些技术。

1.代码示例

// 创建一个Cesium Viewer实例,指定目标DOM元素的id为 "cesiumContainer"
var viewer = new Cesium.Viewer("cesiumContainer", {baseLayerPicker: false,  // 禁用基础图层选择器
});// 创建一个事件处理器,用于处理屏幕空间事件(如点击、拖动)
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);// 创建OpenStreetMap(OSM)建筑物的3D模型
var osmBuildings = Cesium.createOsmBuildings();// 将OSM建筑物添加到场景的primitives集合中
viewer.scene.primitives.add(osmBuildings);// 设置相机视图,定位到指定的经纬度(西雅图附近)和高度
viewer.scene.camera.setView({destination: Cesium.Cartesian3.fromDegrees(-122.3472, 47.598, 370),orientation: {heading: Cesium.Math.toRadians(10), // 方向(水平旋转角度)pitch: Cesium.Math.toRadians(-10)   // 倾斜(垂直旋转角度)}
});// 定义一个函数,用于获取和打印特征的属性
function getFeatureProperty(feature) {let names = feature.getPropertyNames();  // 获取特征属性的名称数组for (var i = 0; i < names.length; i++) {var prop = feature.getProperty(names[i]);  // 获取每个属性的值if (prop) console.log(names[i], prop);     // 打印属性名称和值}
}// 定义一个函数,用于根据距离着色
function showByDistance() {colorByDistanceToCoordinate(47.62051, -122.34931);  // 默认根据指定经纬度着色// 内部函数处理点击事件function move(movement) {viewer.selectEntiy = undefined;var pickBuilding = viewer.scene.pick(movement.position);  // 获取点击位置的建筑物if (pickBuilding) {getFeatureProperty(pickBuilding);  // 获取点击建筑物的属性var latitude = pickBuilding.getProperty("cesium#latitude");var longitude = pickBuilding.getProperty("cesium#longitude");colorByDistanceToCoordinate(latitude, longitude);  // 根据点击的建筑物位置进行着色}}// 设置鼠标左键点击事件的处理函数handler.setInputAction(move, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}// 定义一个函数,根据指定经纬度着色建筑物
function colorByDistanceToCoordinate(pickLatitude, pickLongitude) {osmBuildings.style = new Cesium.Cesium3DTileStyle({defines: {// 定义着色器中的distance变量,计算每个建筑物与指定坐标的距离distance: "distance(vec2(${feature['cesium#longitude']},${feature['cesium#latitude']})," + `vec2(${pickLongitude},${pickLatitude}))`},color: {conditions: [["${distance} > 0.014", "color('blue')"],  // 大于0.014的距离,颜色为蓝色["${distance} > 0.010", "color('green')"], // 大于0.010的距离,颜色为绿色["${distance} > 0.006", "color('yellow')"],// 大于0.006的距离,颜色为黄色["${distance} > 0.0001", "color('red')"],  // 大于0.0001的距离,颜色为红色["true", "color('white')"],                // 其他距离,颜色为白色]}});
}
// 定义一个函数,根据距离渲染建筑物
function showByDistance() {// 首先调用 colorByDistanceToCoordinate,以特定坐标(47.62051, -122.34931)为参考点进行初始着色colorByDistanceToCoordinate(47.62051, -122.34931);// 定义一个内部函数 move 用于处理点击事件function move(movement) {viewer.selectEntiy = undefined;  // 清除当前选择的实体// 获取点击位置的建筑物特征var feature = viewer.scene.pick(movement.position);if (feature) {  // 如果点击位置有建筑物特征getFeatureProperty(feature);  // 获取并打印该建筑物的属性// 获取建筑物的经度和纬度var latitude = feature.getProperty("cesium#latitude");var longitude = feature.getProperty("cesium#longitude");// 调用 colorByDistanceToCoordinate 以点击位置的建筑物为参考点重新着色colorByDistanceToCoordinate(latitude, longitude);}}// 设置鼠标左键点击事件的处理函数,将其与 move 函数绑定handler.setInputAction(move, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}// 调用 showByDistance 函数以启动初始着色和点击事件处理
showByDistance();

2.属性获取原理分析

  当我们点击一个建筑物时,Cesium会自动展示这个建筑物的信息。我们也在控制台输出一下自己获取到的属性信息,看看能不能对应的上。
在这里插入图片描述
在这里插入图片描述
  可以看到完全对应的上。而当我们看下源码就会发现属性获取的调用过程如下:
sequenceDiagram
   participant User as 用户
   participant Scene as Cesium.Scene
   participant Handler as ScreenSpaceEventHandler
   participant Feature as Cesium3DTileFeature
   participant BatchTable as Cesium3DTileBatchTable

User->>Handler: 点击事件
Handler->>Scene: pick(movement.position)
Scene-->>Handler: 返回Cesium3DTileFeature
Handler->>Feature: 获取属性名
Feature->>BatchTable: getPropertyNames()
BatchTable-->>Feature: 返回属性名数组
Feature-->>Handler: 返回属性名数组
Handler->>Feature: 获取属性值(name)
Feature->>BatchTable: getProperty(batchId, name)
BatchTable-->>Feature: 返回属性值
Feature-->>Handler: 返回属性值
Handler-->>User: 打印属性名和值

3.建筑物距离计算原理分析

  在CesiumJS 中,建筑物之间的距离计算是通过 GLSL 着色器来实现的,计算每个建筑物与一个参考点之间的欧几里得距离。以下是距离计算的步骤:

  1. 定义距离计算表达式

    defines: {distance: "distance(vec2(${feature['cesium#longitude']}, ${feature['cesium#latitude']}), vec2(" + `${pickLongitude}, ${pickLatitude}))`
    }
    
    • defines 部分定义了 GLSL 表达式,用于计算每个建筑物与参考点的距离。
    • distance 是 GLSL(OpenGL Shading Language)中的函数,用于计算两个二维向量(坐标)之间的欧几里得距离。
    • vec2 是 GLSL 中表示二维向量的构造函数。
    • ${feature['cesium#longitude']}${feature['cesium#latitude']} 分别表示建筑物的经度和纬度。
    • ${pickLongitude}${pickLatitude} 表示参考点(如用户点击位置)的经度和纬度。
  2. 计算距离

    GLSL 表达式 distance 计算每个建筑物的位置与参考点之间的距离。这个距离值将用于后续的颜色条件判断。

    float distance = distance(vec2(buildingLongitude, buildingLatitude), vec2(referenceLongitude, referenceLatitude));
    
  3. 应用距离值

    这个计算的距离值会被应用到每个建筑物,用于在着色器中进行条件判断,决定建筑物的颜色。

    osmBuildings.style = new Cesium.Cesium3DTileStyle({defines: {distance: "distance(vec2(${feature['cesium#longitude']}, ${feature['cesium#latitude']}), vec2(" + `${pickLongitude}, ${pickLatitude}))`}
    });
    

4.建筑物着色原理分析

  在 CesiumJS 中,建筑物的着色是基于计算出的距离,并通过条件语句来设置颜色的。在 Cesium3DTileStyle中定义颜色条件,根据计算出的距离为建筑物设置颜色。

osmBuildings.style = new Cesium.Cesium3DTileStyle({defines:{distance:"distance(vec2(${feature['cesium#longitude']},${feature['cesium#latitude']}),"+`vec2(${pickLongitude},${pickLatidude}))`},color:{conditions:[["${distance} > 0.014","color('blue')"],["${distance} > 0.010","color('green')"],["${distance} > 0.006","color('yellow')"],["${distance} > 0.0001","color('red')"],["true","color('white')"],]}
})
  1. 定义部分

    • defines 部分定义了 GLSL 表达式,用于计算每个建筑物与参考点的距离。
    • distance 函数使用建筑物的经纬度和参考点的经纬度,计算欧几里得距离。
  2. 颜色条件部分

    • color 部分定义了颜色条件,根据 distance 值设置不同的颜色。
    • 使用条件数组 conditions,依次匹配 distance 的值,并根据匹配的条件设置颜色。

这两个原理共同作用,为用户提供了一个动态且交互的建筑物着色效果,根据点击的位置和距离进行直观的展示。

5.总结

  本文中我们通过代码示例展示了如何在Cesiumjs中对3dtiles进行属性获取、建筑物距离计算、建筑物着色及其原理分析,深入的理解了其原理,回见~

相关文章:

Cesium源码解析六(3dtiles属性获取、建筑物距离计算、建筑物着色及其原理分析)

快速导航 Cesium源码解析一&#xff08;搭建开发环境&#xff09; Cesium源码解析二&#xff08;terrain文件的加载、解析与渲染全过程梳理&#xff09; Cesium源码解析三&#xff08;metadataAvailability的含义&#xff09; Cesium源码解析四&#xff08;metadata元数据拓展…...

AI 情感聊天机器人之旅 —— 相关论文调研

开放域闲聊场景 Prompted LLMs as Chatbot Modules for Long Open-domain Conversation 发布日期&#xff1a;2023-05-01 简要介绍&#xff1a;作者提出了 MPC&#xff08;模块化提示聊天机器人&#xff09;&#xff0c;这是一种无需微调即可创建高质量对话代理的新方法&…...

WPF Prism框架搭建

WPF Prism框架搭建 1.引入Prism框架 在Nuget包管理器中搜索Prism&#xff0c;并添加到项目中 2.在项目中使用prism框架 2.1 修改app.xaml 删除项目中自带的StartupUri 修改Application节点为prism:PrismApplication 引入prism命名空间 <prism:PrismApplication x:C…...

MyBatisplus使用报错--Invalid bound statement

报错如下 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.lotus.mybatis.mapper.UserMapper.selectListat org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235)at com.baomidou.mybatisplus.cor…...

QT-QPainter实现一个动态充电的电池

1、效果 2、核心代码 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimer>...

【云原生】Kubernetes----Metrics-Server组件与HPA资源

目录 引言 一、概述 &#xff08;一&#xff09;Metrics-Server简介 &#xff08;二&#xff09;Metrics-Server的工作原理 &#xff08;三&#xff09;HPA与Metrics-Server的作用 &#xff08;四&#xff09;HPA与Metrics-Server的关系 &#xff08;五&#xff09;HPA与…...

模拟原神圣遗物系统-小森设计项目,设计圣遗物(生之花,死之羽,时之沙,空之杯,理之冠)抽象类

分析圣遗物 在圣遗物系统&#xff0c;玩家操控的是圣遗物的部分 因此我们应该 物以类聚 人与群分把每个圣遗物的部分&#xff0c;抽象出来 拿 生之花&#xff0c;死之羽为例 若是抽象 类很好的扩展 添加冒险家的生之花 时候继承生之花 并且名称冒险者- 生之花 当然圣遗物包含…...

仿真模拟--telnet服务两种认证模式(自作)

自己做的笔记,有问题或看不懂请见解一下~ 目录 两个路由器间实现telnet服务(password认证模式) server client 两个路由器间实现telnet服务(aaa认证模式) server client 改名 tab键补齐 不会就扣问号 ? save 两个路由器间实现telnet服务…...

Apple Phone Memory

Apple Phone Memory 苹果手机内存查询&#xff0c;哪些应用程序&#xff08;app&#xff09;占用内存&#xff1a; 设置 通用 iPhone储存空间 清理下QQ音乐&#xff1a;...

Kubernetes容器运行时:Containerd vs Docke

容器化技术笔记 Kubernetes容器运行时&#xff1a;Containerd vs Docke - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this arti…...

【java 线程的状态】

介绍 Java 线程在运⾏的⽣命周期中的指定时刻只可能处于下⾯ 6 种不同状态的其中⼀个状态 状态名称说明NEW初始状态,线程被构建,但是还没有调用start()方法RUNNABLE运行状态,Java线程将操作系统中的就绪和运行两种状态统称为"运行中"BLOCKED阻塞状态,表示线程阻塞于…...

php加密验签

签名生成步骤&#xff08;小程序端/前端&#xff09;&#xff1a; 确定参与签名的参数&#xff1a;选择需要参与签名的请求参数&#xff0c;通常包括请求的时间戳、随机数、请求的数据等。 参数排序与拼接&#xff1a;将所有参与签名的参数按照字母顺序排序&#xff0c;并拼接成…...

【Golang - 90天从新手到大师】Day06 - 数组

系列文章合集 Golang - 90天从新手到大师 数组是golang中最常用的一种数据结构,数组就是同一类型数据的有序集合 定义一个数组 格式: var name [n]type n为数组长度,n>0 且无法修改,type为数组的元素类型如: var a [2]int上面的例子定义了一个长度为2,元素类型为int的数组…...

java的有参构造方法

java的有参构造方法和无参构造方法类似&#xff0c;区别是构造方法名称里后面跟着一个括号&#xff0c;括号里是参数的定义 示例代码如下 class student4{private String name;private int age;public student4(String n,int a) {namen;agea;System.out.println("调用了…...

Vue66-vue-默认插槽

一、默认插槽需求 1-1、原本的写法&#xff1a; 在每个category组件中用v-show来做条件渲染&#xff0c;但是不方便&#xff01; 1-2、默认插槽 img标签&#xff0c;ul标签&#xff0c;video标签&#xff0c;都是在app组件中完成解析之后&#xff0c;塞到category组件中的&…...

tsf-consul的使用

在腾讯云微服务平台TSF中使用Consul作为服务发现组件,通常需要遵循以下步骤: ### 1. 创建应用 首先,您需要在TSF控制台创建一个应用。在创建应用时,选择合适的业务类型、开发语言、开发框架等信息。对于使用Consul作为服务发现组件的Spring Cloud应用,您需要选择“业务应…...

【perl】基本语法 /备忘录/

分享 perl 语言学习资源 Perl 教程|极客教程 (geek-docs.com) Perl [zh] (runebook.dev) Perl 运算符 | 菜鸟教程 (runoob.com) Perl Documentation - Perldoc Browser Search the CPAN - metacpan.org 当然还有一些经典书籍&#xff0c;不再列举。 1、数字 1.1、数字表…...

mongodb 集群安装

整体架构图&#xff1a; 1. 配置域名 Server1&#xff1a; OS version: CentOS Linux release 8.5.2111 hostnamectl --static set-hostname mongo01 vi /etc/sysconfig/network # Created by anaconda hostnamemong01 echo "192.168.88.20 mong1 mongo01.com mongo…...

绿茶集团重启IPO:流量渐退、业绩波动,还能讲出好故事吗?

近日&#xff0c;绿茶集团有限公司(下称“绿茶集团”)向港交所递交上市申请&#xff0c;花旗、招银国际为其联席保荐人。 回望绿茶集团的上市之路&#xff0c;可谓有诸多坎坷。该公司于2021年3月首度向港交所发起冲击&#xff0c;但却将中文版招股书中的“流动负债总额”错写成…...

Git与SSH

Git Git是一种分布式版本控制系统&#xff0c;最初由Linus Torvalds为管理Linux内核开发而设计并开发。Git可以帮助开发团队协作管理代码&#xff0c;跟踪代码变更历史&#xff0c;并在需要时回溯到特定版本。 分布式版本控制&#xff1a;每个开发者都可以拥有完整的代码仓库…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...