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

news2024/12/22 15:35:24

快速导航

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进行属性获取、建筑物距离计算、建筑物着色及其原理分析,深入的理解了其原理,回见~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【因果推断python】46_估计量2

目录 连续型干预变量案例 非线性处理效果 关键思想 连续型干预变量案例 目标转换方法的另一个明显缺点是它仅适用于离散或二元处理。这是你在因果推理文献中经常看到的东西。大多数研究都是针对二元干预案例进行的&#xff0c;但您找不到很多关于连续干预的研究。这让我很困…

Javase.String 类

String 类 【本节目标】1. String类的重要性2. 常用方法2.1 字符串构造2.2 String对象的比较2.3 字符串查找2.4 转化2.5 字符串替换2.7 字符串截取2.8 其他操作方法2.9 字符串的不可变性2.10 字符串修改 3. StringBuilder和StringBuffer3.2 面试题&#xff1a; 4. String类oj4.…

使用虚拟滚动条优化通过el-collapse展示多条数据的性能问题

我们将一个10000条的数据通过el-collapse展示出来&#xff0c;同时在点开每一个item时&#xff0c;要内置一个编辑器&#xff0c;对文本内容进行编辑。其实&#xff0c;如果仅10000条数据的文本的单独展示&#xff0c;可能性能不会太差&#xff0c;但由于每一条都需要带有一个文…

web中间件漏洞-jboss部署war包

web中间件漏洞-jboss部署war包 攻击机服务器准备好的ma.war

FreeBSD在zfs挂接第二块ssd 硬盘

为FreeBSD机器新增加了一块ssd硬盘&#xff1a;骑尘 256G 先格式化分区硬盘 进入bsdconfig 选Disk Management 选择ada1 &#xff0c;也就是新增加的硬盘 选择auto 然后选择Entire Disk 提示信息 The existing partition scheme on this disk (MBR) │ …

Python数据科学 | 是时候跟Conda说再见了

本文来源公众号“Python数据科学”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;是时候跟Conda说再见了 1 简介 conda作为Python数据科学领域的常用软件&#xff0c;是对Python环境及相关依赖进行管理的经典工具&#xff0c;通…

容声神助攻!欧洲杯最刺激一战诞生,神来之笔背后有高人

2-2&#xff0c;当比分最终被定格在这个数字时&#xff0c;克罗地亚的老将们即使职业生涯已经经历了太多太多惨烈的比赛&#xff0c;此刻依然难掩心中的复杂情绪。 欧洲杯开赛至今最刺激的一战&#xff0c;从0-1落后的长时间焦虑&#xff0c;到下半场3分钟扳平反超的狂喜&…

【嵌入式Linux】<总览> 文件IO(更新中)

文章目录 前言 一、常用函数 1. open函数 2. close函数 3. write函数 4. read函数 5. dup函数 6. dup2函数 二、文件读写细节 1. 换行符 2. 文件描述符 3. errno和perror 前言 在Linux系统中&#xff0c;一切皆文件。因此&#xff0c;掌握Linux下文件IO常用的函数…

为什么美业门店要用专业的美业系统?博弈美业SaaS管理系统Java源码分享

美容、医美等美业门店需要使用专业的美业系统&#xff0c;而不是普通的管理系统&#xff0c;美业专用系统的优势在哪&#xff1f; 专业的美业系统与普通系统相比&#xff0c;更加贴合美业门店的经营需求&#xff0c;提供了更全面、便捷、高效的管理功能&#xff0c;有助于提升…

端到端自动驾驶的基础概念

欢迎大家关注我的B站&#xff1a; 偷吃薯片的Zheng同学的个人空间-偷吃薯片的Zheng同学个人主页-哔哩哔哩视频 (bilibili.com) 目录 1.端到端自动驾驶的定义 1.1特斯拉FSD 1.2端到端架构演进 1.3大模型 1.4世界模型 1.5纯视觉传感器 2.落地的挑战 1.端到端自动驾驶的定…

RSA学习

[MRCTF2020]Easy_RSA 先来分析一下这个RSA代码的特殊性&#xff0c;这个不是传统的RSA,随机生成N&#xff0c;并保证为N%8的余数是5 zlib 用于数据压缩&#xff0c;但是并似乎没有用到 gen_p(): 生成随机的1024位质数p。计算np*q&#xff0c;并没有直接用于加密。计算F_n…

返回给前端数据的封装

返回格式如下&#xff1a; { "code": 200/400, "msg": "成功"/"失败", "total": n, "data": [ {}&#xff0c;{}]} 1.在common中新增Result 类&#xff0c;代码如下 package com.xxx0523.common; import lombo…

【OpenVINO™】使用 OpenVINO™ C# 异步推理接口部署YOLOv8 ——在Intel IGPU 上速度依旧飞起!!

OpenVINO Runtime支持同步或异步模式下的推理。Async API的主要优点是&#xff0c;当设备忙于推理时&#xff0c;应用程序可以并行执行其他任务&#xff08;例如&#xff0c;填充输入或调度其他请求&#xff09;&#xff0c;而不是等待当前推理首先完成。 当我们使用异步API时&…

【React】使用Token做路由权限控制

在components/AuthRoute/index.js中 import { getToken } from /utils import { Navigate } from react-router-domconst AuthRoute ({ children }) > {const isToken getToken()if (isToken) {return <>{children}</>} else {return <Navigate to"/…

算法设计与分析 实验4 动态规划法求扔鸡蛋问题

目录 一、实验目的 二、问题描述 三、实验要求 四、实验内容 动态规划法 算法描述 算法伪代码描述 算法复杂度分析 数据测试 二分优化的动态规划法 算法描述 二分优化&#xff1a; 算法伪代码 算法复杂度分析 数据测试 单调决策优化的动态规划法 算法描述 算…

【机器学习】与【深度学习】的前沿探索——【GPT-4】的创新应用

gpt4o年费&#xff1a;一年600&#xff0c; 友友们&#xff0c;一起拼单呀&#xff0c;两人就是300&#xff0c;三个人就是200&#xff0c;以此类推&#xff0c; 我已经开通年费gpt4o&#xff0c;开通时长是 从2024年6月20日到2025年7月16日 有没有一起的呀&#xff0c;有需要的…

vue3页面传参

一&#xff0c;用query传参 方法&#xff1a; router.push({path: ‘路由地址’, query: ‘参数’}) 例子&#xff1a;a页面携带参数跳转到b页面并且b页面拿到a页面传递过来的参数 在路由router.ts配置 a页面&#xff1a; <template><div >a页面</div>…

Spatio-temporal Relation Modeling for Few-shot Action Recognition

标题&#xff1a;少样本动作识别的时空关系建模 源文链接&#xff1a;Thatipelli_Spatio-Temporal_Relation_Modeling_for_Few-Shot_Action_Recognition_CVPR_2022_paper.pdf (thecvf.com)https://openaccess.thecvf.com/content/CVPR2022/papers/Thatipelli_Spatio-Temporal_…

多目标跟踪中用到的求解线性分配问题(Linear Assignment Problem,LAP)Python

多目标跟踪中用到的求解线性分配问题&#xff08;Linear Assignment Problem&#xff0c;LAP&#xff09;Python flyfish 如果想看 C版本的&#xff0c;请点这里。 线性分配问题&#xff08;LAP&#xff0c;Linear Assignment Problem&#xff09;是一个经典的优化问题&…

虚拟机配置桥接模式

背景 因为要打一些awd比赛,一些扫描工具什么的,要用到kali,就想着换成一个桥接模式 但是我看网上的一些文章任然没弄好,遇到了一些问题 前置小问题 每次点开虚拟网络编辑器的时候都没有vmnet0,但是点击更改的时候却有vmnet0 第一步: 点击更改设置 第二步: 把wmnet0删掉 …