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 着色器来实现的,计算每个建筑物与一个参考点之间的欧几里得距离。以下是距离计算的步骤:
-
定义距离计算表达式:
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}表示参考点(如用户点击位置)的经度和纬度。
-
计算距离:
GLSL 表达式
distance计算每个建筑物的位置与参考点之间的距离。这个距离值将用于后续的颜色条件判断。float distance = distance(vec2(buildingLongitude, buildingLatitude), vec2(referenceLongitude, referenceLatitude)); -
应用距离值:
这个计算的距离值会被应用到每个建筑物,用于在着色器中进行条件判断,决定建筑物的颜色。
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')"],]}
})
-
定义部分:
defines部分定义了 GLSL 表达式,用于计算每个建筑物与参考点的距离。distance函数使用建筑物的经纬度和参考点的经纬度,计算欧几里得距离。
-
颜色条件部分:
color部分定义了颜色条件,根据distance值设置不同的颜色。- 使用条件数组
conditions,依次匹配distance的值,并根据匹配的条件设置颜色。
这两个原理共同作用,为用户提供了一个动态且交互的建筑物着色效果,根据点击的位置和距离进行直观的展示。
5.总结
本文中我们通过代码示例展示了如何在Cesiumjs中对3dtiles进行属性获取、建筑物距离计算、建筑物着色及其原理分析,深入的理解了其原理,回见~
相关文章:
Cesium源码解析六(3dtiles属性获取、建筑物距离计算、建筑物着色及其原理分析)
快速导航 Cesium源码解析一(搭建开发环境) Cesium源码解析二(terrain文件的加载、解析与渲染全过程梳理) Cesium源码解析三(metadataAvailability的含义) Cesium源码解析四(metadata元数据拓展…...
AI 情感聊天机器人之旅 —— 相关论文调研
开放域闲聊场景 Prompted LLMs as Chatbot Modules for Long Open-domain Conversation 发布日期:2023-05-01 简要介绍:作者提出了 MPC(模块化提示聊天机器人),这是一种无需微调即可创建高质量对话代理的新方法&…...
WPF Prism框架搭建
WPF Prism框架搭建 1.引入Prism框架 在Nuget包管理器中搜索Prism,并添加到项目中 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资源
目录 引言 一、概述 (一)Metrics-Server简介 (二)Metrics-Server的工作原理 (三)HPA与Metrics-Server的作用 (四)HPA与Metrics-Server的关系 (五)HPA与…...
模拟原神圣遗物系统-小森设计项目,设计圣遗物(生之花,死之羽,时之沙,空之杯,理之冠)抽象类
分析圣遗物 在圣遗物系统,玩家操控的是圣遗物的部分 因此我们应该 物以类聚 人与群分把每个圣遗物的部分,抽象出来 拿 生之花,死之羽为例 若是抽象 类很好的扩展 添加冒险家的生之花 时候继承生之花 并且名称冒险者- 生之花 当然圣遗物包含…...
仿真模拟--telnet服务两种认证模式(自作)
自己做的笔记,有问题或看不懂请见解一下~ 目录 两个路由器间实现telnet服务(password认证模式) server client 两个路由器间实现telnet服务(aaa认证模式) server client 改名 tab键补齐 不会就扣问号 ? save 两个路由器间实现telnet服务…...
Apple Phone Memory
Apple Phone Memory 苹果手机内存查询,哪些应用程序(app)占用内存: 设置 通用 iPhone储存空间 清理下QQ音乐:...
Kubernetes容器运行时:Containerd vs Docke
容器化技术笔记 Kubernetes容器运行时:Containerd vs Docke - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this arti…...
【java 线程的状态】
介绍 Java 线程在运⾏的⽣命周期中的指定时刻只可能处于下⾯ 6 种不同状态的其中⼀个状态 状态名称说明NEW初始状态,线程被构建,但是还没有调用start()方法RUNNABLE运行状态,Java线程将操作系统中的就绪和运行两种状态统称为"运行中"BLOCKED阻塞状态,表示线程阻塞于…...
php加密验签
签名生成步骤(小程序端/前端): 确定参与签名的参数:选择需要参与签名的请求参数,通常包括请求的时间戳、随机数、请求的数据等。 参数排序与拼接:将所有参与签名的参数按照字母顺序排序,并拼接成…...
【Golang - 90天从新手到大师】Day06 - 数组
系列文章合集 Golang - 90天从新手到大师 数组是golang中最常用的一种数据结构,数组就是同一类型数据的有序集合 定义一个数组 格式: var name [n]type n为数组长度,n>0 且无法修改,type为数组的元素类型如: var a [2]int上面的例子定义了一个长度为2,元素类型为int的数组…...
java的有参构造方法
java的有参构造方法和无参构造方法类似,区别是构造方法名称里后面跟着一个括号,括号里是参数的定义 示例代码如下 class student4{private String name;private int age;public student4(String n,int a) {namen;agea;System.out.println("调用了…...
Vue66-vue-默认插槽
一、默认插槽需求 1-1、原本的写法: 在每个category组件中用v-show来做条件渲染,但是不方便! 1-2、默认插槽 img标签,ul标签,video标签,都是在app组件中完成解析之后,塞到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 当然还有一些经典书籍,不再列举。 1、数字 1.1、数字表…...
mongodb 集群安装
整体架构图: 1. 配置域名 Server1: 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:流量渐退、业绩波动,还能讲出好故事吗?
近日,绿茶集团有限公司(下称“绿茶集团”)向港交所递交上市申请,花旗、招银国际为其联席保荐人。 回望绿茶集团的上市之路,可谓有诸多坎坷。该公司于2021年3月首度向港交所发起冲击,但却将中文版招股书中的“流动负债总额”错写成…...
Git与SSH
Git Git是一种分布式版本控制系统,最初由Linus Torvalds为管理Linux内核开发而设计并开发。Git可以帮助开发团队协作管理代码,跟踪代码变更历史,并在需要时回溯到特定版本。 分布式版本控制:每个开发者都可以拥有完整的代码仓库…...
SDMatte模型推理性能剖析:使用Profiling工具定位计算瓶颈
SDMatte模型推理性能剖析:使用Profiling工具定位计算瓶颈 1. 为什么需要性能剖析 做AI模型推理优化就像修车一样,你得先知道哪里出了问题才能对症下药。SDMatte作为一款专业的图像抠图模型,在实际部署中经常会遇到推理速度慢、资源占用高等…...
Phi-3-mini-128k-instruct与STM32开发:生成嵌入式C代码与调试逻辑
Phi-3-mini-128k-instruct与STM32开发:生成嵌入式C代码与调试逻辑 1. 引言 如果你玩过STM32,尤其是像STM32F103C8T6这种经典的“蓝色药丸”最小系统板,肯定对下面这些场景不陌生:为了点亮一个LED,翻遍数据手册&#…...
4个让OneNote效率倍增的开源效率工具:Markdown全功能增强方案
4个让OneNote效率倍增的开源效率工具:Markdown全功能增强方案 【免费下载链接】NoteWidget Markdown add-in for Microsoft Office OneNote 项目地址: https://gitcode.com/gh_mirrors/no/NoteWidget 一、问题发现:OneNote的专业创作短板与解决方…...
DAMO-YOLO实战:用AI视觉系统做内容安全审核与统计
DAMO-YOLO实战:用AI视觉系统做内容安全审核与统计 1. 引言:当AI视觉遇见内容安全 在数字内容爆炸式增长的今天,如何高效地进行内容审核成为许多平台面临的挑战。传统人工审核不仅效率低下,而且容易因疲劳导致误判。本文将介绍如…...
Unity卡牌UI框架实战:构建高性能游戏界面的深度策略
Unity卡牌UI框架实战:构建高性能游戏界面的深度策略 【免费下载链接】UiCard Generic UI for card games like Hearthstone, Magic Arena and Slay the Spire... 项目地址: https://gitcode.com/gh_mirrors/ui/UiCard 在卡牌游戏开发领域,UI交互的…...
AI 模型推理框架性能分析与对比
AI模型推理框架性能分析与对比 随着人工智能技术的快速发展,AI模型推理框架成为支撑各类应用落地的核心工具。无论是计算机视觉、自然语言处理还是推荐系统,高效的推理框架直接影响模型的响应速度、资源占用和部署成本。本文将从多个维度对比主流AI推理…...
煤矿电液阀系统摄像仪护套连接器 DLJ01(1000)参数
在煤矿综采工作面液压支架电液控制系统中,摄像仪护套连接器 DLJ01(1000)作为矿用本安型摄像仪与电源、信号传输线缆之间的专用接口,承担着视频信号与供电的稳定传输任务。其型号中的“1000”代表线缆长度为1000mm(1米),…...
5V与3.3V MCU串口电平转换电路设计
不同工作电压MCU间的串口电平转换电路设计1. 项目概述1.1 问题背景在现代嵌入式系统设计中,经常遇到不同工作电压的微控制器(MCU)之间需要进行串口通信的场景。例如:MCU1工作电压:5VMCU2工作电压:3.3V若直接将两个MCU的TX、RX引脚…...
Pixel Fashion Atelier保姆级教程:如何将生成结果无缝导入Aseprite进行二次编辑
Pixel Fashion Atelier保姆级教程:如何将生成结果无缝导入Aseprite进行二次编辑 1. 教程概述 Pixel Fashion Atelier是一款基于Stable Diffusion与Anything-v5的像素风格图像生成工具,特别适合创作复古RPG风格的时尚设计。本教程将手把手教你如何将生成…...
Remotery WebSocket通信机制:浏览器端性能数据可视化
Remotery WebSocket通信机制:浏览器端性能数据可视化 【免费下载链接】Remotery Single C file, Realtime CPU/GPU Profiler with Remote Web Viewer 项目地址: https://gitcode.com/gh_mirrors/re/Remotery Remotery作为一款轻量级实时CPU/GPU性能分析工具&…...
