Cesium.js--》探秘Cesium背后的3D模型魔力—加载纽约模型

今天简单实现一个Cesium.js的小Demo,加强自己对Cesium知识的掌握与学习,先简单对这个开源库进行一个简单的介绍吧!

Cesium 是一个开源的地理空间可视化引擎,用于创建基于 Web 的三维地球应用程序。它允许开发人员在网页上呈现高度可视化的地球数据,包括地形、卫星影像、建筑物、地理信息系统 (GIS) 数据等。其提供了强大的 JavaScript 库和 API,使开发人员可以轻松地构建交互式、高性能的地球应用。

总的来说,Cesium 是一个强大的工具,可以帮助开发者构建高度交互和可视化的地球应用,适用于各种领域,包括地理信息系统、虚拟旅游、航空航天等。接下来开始正式的学习!

目录

项目搭建

添加纽约建筑模型

划分城市区域

设置地图标记

设置模型运动轨迹


项目搭建

本案例还是借助框架书写cesium项目,借用vite构建工具搭建vue项目,vite这个构建工具如果有不了解的朋友,可以参考我之前对其讲解的文章:vite脚手架的搭建与使用。搭建完成之后,用编辑器打开该项目,在终端执行 npm i 安装一下依赖即可。

接下来简单的介绍一下Cesium,该开源库在vite官网社区插件中已经给出了相关的链接,如下:

社区插件链接中提供了许多vite工具集成的插件,并提供了相关插件的链接,cesium如下:

我们点击该 链接 ,就跳转到cesium相关介绍的github页面,这里提供了该插件的下载命令以及相关的配置使用介绍,下载命令如下,直接复制即可:

npm i cesium vite-plugin-cesium vite -D

根据官网的介绍,我们需要在vite.config.js中进行相应的代码配置,如下:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 导入cesium插件
import cesium from 'vite-plugin-cesium';export default defineConfig({plugins: [vue(), cesium()], // 调用cesium插件
})

配置完成之后,我们回到App根组件,然后我们引入cesium的全局对象进行测试,如下:

<template><div id="cesiumContainer"></div>
</template><script setup>
import { ref, onMounted } from 'vue'
import * as Cesium from 'cesium';onMounted(() => {const viewer = new Cesium.Viewer('cesiumContainer', { infoBox: false });});
</script><style scoped lang="scss">
#cesiumContainer {width: 100%;height: 100vh;overflow: hidden;
}
</style>

运行我们的项目,打开浏览器就可以看到我们下面的一个地球样式,我们也可以对其进行相关操作

当然我们也可以查看 https://cesium.com/  查阅相关Cesium相关的知识:

通过翻阅 Cesium相关API进行查看相应的使用    提供了相应的解释:

我们对代码进行如下修改,可以查看到相应的地形地貌:

onMounted(() => {let custom = new Cesium.ArcGisMapServerImageryProvider({url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'});const viewer = new Cesium.Viewer('cesiumContainer', { infoBox: false, // 关闭信息窗口imageryProvider: custom, // 自定义图层terrain: Cesium.Terrain.fromWorldTerrain(), // 开启地形});
});

当然我们也可以设置一开始聚焦的相机位置:

onMounted(() => {let custom = new Cesium.ArcGisMapServerImageryProvider({url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'});const viewer = new Cesium.Viewer('cesiumContainer', { infoBox: false, // 关闭信息窗口imageryProvider: custom, // 自定义图层terrain: Cesium.Terrain.fromWorldTerrain(), // 开启地形});viewer.camera.setView({destination: Cesium.Cartesian3.fromDegrees(116.2317, 39.5427, 200), // 坐标orientation: {heading: Cesium.Math.toRadians(90), // 方向pitch: Cesium.Math.toRadians(25), // 倾斜}})
});

定位的坐标方向,画面还是挺壮观的。(我爱说实话!)

添加纽约建筑模型

根据上文我们了解到的cesium的基本操作,接下来我们拿纽约这个地方进行举例,首先我们先掌握如何加载模型,我们打开 cesium官网 ,进行一个简单的注册,该官网和github联动的,和github关联一下即可,注册完毕会进入我们这一个控制台,如下:

因为纽约模型,cesium官网是提供的,我们点击Asset Depot选择相应的模型添加到My Assets:

选择我们相应添加的模型,复制代码到我们的项目即可,非常方便:

我们在场景加载的时候相机直接定位到纽约的位置,然后加载纽约的模型,如下:

onMounted(async () => {let custom = new Cesium.ArcGisMapServerImageryProvider({url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'});const viewer = new Cesium.Viewer('cesiumContainer', { infoBox: false, // 关闭信息窗口imageryProvider: custom, // 自定义图层terrain: Cesium.Terrain.fromWorldTerrain(), // 开启地形});viewer.camera.setView({destination:new Cesium.Cartesian3(1332761, -4662399, 4137888),orientation:{heading: 0.60,pitch: -0.66}})// 加载3DTiles纽约数据let city = viewer.scene.primitives.add( await Cesium.Cesium3DTileset.fromIonAssetId(2275207));
});

最终达到的效果如下,画面还不错(我爱说实话!)

划分城市区域

接下来我们通过GeoJSON来划分城市区域,GeoJSON(JavaScript Object Notation, 简称JSON)是一种对各种地理数据结构进行编码的格式,基于Javascript对象表示法的地理空间信息数据交换格式,可以表示几何、特征或者特征集合。

接下来我们调用GeoJson文件加载纽约区域的领域边界:

// 调用 GeoJson 文件加载邻域边界
let neighborhoodsPromise = Cesium.GeoJsonDataSource.load('/public/assets/SampleData/sampleNeighborhoods.geojson');

接下来将加载的地理数据(如街区或区域)添加到 Cesium 地球查看器(viewer)中,并对这些数据进行着色调整,并确保它们贴在地图表面上。

// 贴在地图表面
neighborhoodsPromise.then((dataSource) => {// 将数据添加到查看器viewer.dataSources.add(dataSource);// 把数据进行着色的调整以及放到地图的表面// 拿到区域的实例  Get the array of entitieslet neighborhoodsEntities = dataSource.entities.values;for (let i = 0; i < neighborhoodsEntities.length; i++) {let entity = neighborhoodsEntities[i];// 判断存不存在相应的图形 if (Cesium.defined(entity.polygon)) {entity.name = entity.properties.neighborhood;// 设置多边形颜色entity.polygon.material = Cesium.Color.fromRandom({red: 0.1, // 随机颜色maximumGreen: 0.5, // 最大绿色minimumBlue: 0.5, // 最小蓝色alpha: 0.6 // 透明度});// 设置地形着色entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;// 设置位置 贴到多边形最底下let polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;entity.position = Cesium.Ellipsoid.WGS84.scaleToGeocentricSurface(Cesium.BoundingSphere.fromPoints(polyPositions).center,);}}
})

加载地理数据并在地图上显示,同时对加载的多边形进行着色调整,并确保它们贴在地球表面上,并为每个多边形添加标签。

// 生成标签
entity.label = {text: entity.name,showBackground: true,scale: 0.6,horizontalOrigin: Cesium.HorizontalOrigin.CENTER,verticalOrigin: Cesium.VerticalOrigin.BOTTOM,// 设置显示的距离范围distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10, 8000),// 禁用的距离disableDepthTestDistance: 100
}

最终呈现的效果如下所示:

然后我们也可以通过鼠标点击某个标签进行区域的锁定,然后滑动鼠标进行详细查看:

设置地图标记

接下来通过KML文件进行图标标记,KML文件是谷歌公司创建的一种地标性文件,用于记录某一地点、或连续地点的时间、经度、纬度、海拔等地理信息数据,供GE等有关软件使用。

let kmlOptions = {camera : viewer.scene.camera,canvas : viewer.scene.canvas,// 如果我们想要将几何特征(多边形、线串和线性环)固定在地面上,则为 true。clampToGround : true
};
let geocachePromise = Cesium.KmlDataSource.load('/public/assets/SampleData/sampleGeocacheLocations.kml', kmlOptions);

接下来将 geocache 广告牌实体添加到场景中并为其设置样式:

geocachePromise.then(function(dataSource) {// 将新数据作为实体添加到查看器viewer.dataSources.add(dataSource);// 获取实体数组var geocacheEntities = dataSource.entities.values;for (var i = 0; i < geocacheEntities.length; i++) {var entity = geocacheEntities[i];if (Cesium.defined(entity.billboard)) {// 调整垂直原点,使图钉位于地形上entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;entity.billboard.image = '/public/assets/tagpark.png'// 禁用标签以减少混乱entity.label = undefined;// 添加距离显示条件entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10.0, 20000.0);// 以度为单位计算纬度和经度var cartographicPosition = Cesium.Cartographic.fromCartesian(entity.position.getValue(Cesium.JulianDate.now()));var latitude = Cesium.Math.toDegrees(cartographicPosition.latitude);var longitude = Cesium.Math.toDegrees(cartographicPosition.longitude);// 修改描述var description = '<table class="cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>' +'<tr><th>' + "Longitude" + '</th><td>' + longitude.toFixed(5) + '</td></tr>' +'<tr><th>' + "Latitude" + '</th><td>' + latitude.toFixed(5) + '</td></tr>' +'<tr><th>' + "实时人流" + '</th><td>' + Math.floor(Math.random()*20000)  + '</td></tr>' +'<tr><th>' + "安全等级" + '</th><td>' + Math.floor(Math.random()*5)  + '</td></tr>' +'</tbody></table>';entity.description = description;}}
});

最终呈现的效果如下所示,感觉还不错!(我爱说实话)

设置模型运动轨迹

接下来我们实现一个3D模型沿着地图上我们设置的轨迹进行运动,这里需要加载一个czml文件,该文件是一种用于描述三维场景的文本格式,通常与Cesium.js一起使用。它允许开发者以一种结构化的方式描述地球上的实体、图形、动画和其他地理空间信息,从而创建动态的、交互式的地理可视化应用程序。具体代码如下:

// 从czml文件加载模型运动路径
var dronePromise = Cesium.CzmlDataSource.load('/public/assets/SampleData/sampleFlight.czml');// 模型实体
var drone;
dronePromise.then(function(dataSource){viewer.dataSources.add(dataSource);drone = dataSource.entities.getById('Aircraft/Aircraft1');drone.model = {// uri:'/public/assets/SampleData/Models/CesiumDrone.gltf', // 飞机模型uri:'/public/assets/SampleData/Models/ferrari2.gltf', // 汽车模型minimumPixelSize:128, // 最小像素大小maximumScale:1000, // 最大比例silhouetteColor:Cesium.Color.WHITE, // 轮廓颜色silhouetteSize:2 // 轮廓大小}drone.orientation = new Cesium.VelocityOrientationProperty(drone.position); // 运行姿态drone.viewFrom = new Cesium.Cartesian3(0,-30,30) // 运行视角viewer.clock.shouldAnimate = true; // 自动播放
})

最终达到的效果如下:

CZML文件可以手动编写,也可以由各种地理信息系统(GIS)工具或数据源生成。它使用JSON格式,因此易于阅读和编辑。Cesium.js库能够解析和渲染CZML文件,从而在Web浏览器中呈现出动态的地理可视化效果,如下可以看到czml对路径的绘制:

ok,效果完成了,喜欢的朋友点个赞收藏一下吧!

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

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

相关文章

Java基础第十一课——类与对象(2)

由于类与对象这一部分的知识点很多&#xff0c;而且操作方法也有很多&#xff0c;所以这次将继续深入讨论一下关于类与对象中方法传参、方法重载、构造方法以及this关键字使用方面的知识。 一、方法传参 1.return关键字 return关键字作用 作用场景&#xff1a;方法内 作用…

天猫精灵要会员,不能听歌,还能用来干什么呢?榨干它的剩余价值

目录 起因&#xff1a;以听歌为主要功能的设备&#xff0c;却不能听歌了 1.蓝牙音箱 2.控制智能家电 3.万能遥控器&#xff0c;需要一个外接设备 4.倒计时/提醒&#xff0c;闹钟提醒&#xff0c;整点提醒&#xff08;这功能有人不喜欢&#xff0c;闲吵&#xff0c;还不能关…

LeetCode题练习与总结:最小路径和--64

一、题目描述 给定一个包含非负整数的 m x n 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。 说明&#xff1a;每次只能向下或者向右移动一步。 示例 1&#xff1a; 输入&#xff1a;grid [[1,3,1],[1,5,1],[4,2,1]] 输出…

UI设计规范

一套商城系统的诞生&#xff0c;除了代码的编写&#xff0c;UI设计也至关重要。UI设计关系到商城系统的最终呈现效果&#xff0c;关乎整体商城的风格展现&#xff0c;如果UI设计做不好&#xff0c;带来的负面影响也是不容小觑的。 1、在很多商城系统开发中&#xff0c;有时会有…

【Sql Server】锁表如何解锁,模拟会话事务方式锁定一个表然后进行解锁

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂》。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言创建表模拟…

运放噪声评估的来龙去脉

运放噪声评估的来龙去脉 友情提示&#xff0c;运放电路的噪声分析还是比较复杂的&#xff0c;不论是基础理论还是对应的推导过程&#xff0c;都不是特别容易。考虑到兄弟们的基础参差不齐&#xff0c;所以我还是尽量说清楚点&#xff0c;这样导致看起来就有点罗里吧嗦&#xff…

10 Php学习:循环

在 PHP 中&#xff0c;提供了下列循环语句&#xff1a; while - 只要指定的条件成立&#xff0c;则循环执行代码块do…while - 首先执行一次代码块&#xff0c;然后在指定的条件成立时重复这个循环for - 循环执行代码块指定的次数foreach - 根据数组中每个元素来循环代码块 当…

【Java EE】获取Cookie和Session

文章目录 &#x1f38d;Cookie简介&#x1f340;理解Session&#x1f333;Cookie 和 Session 的区别&#x1f332;获取Cookie&#x1f338;传统获取Cookie&#x1f338;简洁获取Cookie &#x1f334;获取Session&#x1f338;Session存储&#x1f338;Session读取&#x1f33b;…

Fence同步

在《Android图形显示系统》没有介绍到帧同步的相关概念&#xff0c;这里简单介绍补充一下。 在图形显示系统中&#xff0c;图形缓存GraphicBuffer可以被不同的硬件来访问&#xff0c;如CPU、GPU、HWC都可以对缓存进行读写&#xff0c;如果同时对图形缓存进行操作&#xff0c;有…

mysql8.0高可用集群架构实战

MySQL :: MySQL Shell 8.0 :: 7 MySQL InnoDB Cluster 基本概述 InnoDB Cluster是MySQL官方实现高可用读写分离的架构方案,其中包含以下组件 MySQL Group Replication,简称MGR,是MySQL的主从同步高可用方案,包括数据同步及角色选举Mysql Shell 是InnoDB Cluster的管理工具,用…

java项目之校园兼职系统(ssm框架+mysql数据库+文档)

项目简介 校园兼职系统的主要使用者分为&#xff1a;管理员&#xff1a;首页、个人中心、专业管理、商家管理、热门兼职管理、学生管理、兼职接单管理、学生咨询管理、兼职任务管理、完成评价管理、管理员管理、系统管理等模块信息的查看及相应操作&#xff1b;学生&#xff1…

OpenCV C++学习笔记

1.图像的读取与显示 1.1 加载并显示一张图片 #include<opencv2/opencv.hpp> #include<iostream>using namespace cv; using namespace std; int main(int argc,char** argv){Mat srcimread("sonar.jpg");//读取图像if(src.empty()){printf("Could…

超越传统Lambda函数:深入解析Out-of-line Lambdas的奇妙之处

超越传统函数&#xff1a;深入解析线外 Lambda函数 的奇妙之处 一、背景二、lambda 的捕获三、可能出现的警告四、lambda的广义捕获五、为每种情况进行重载六、总结 一、背景 Out-of-line Lambdas翻译过来就是“线外Lambda函数”或“离线Lambda函数”。Lambda 是使代码更具表现…

力扣 | 234. 回文链表

用到快慢指针&#xff01; /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { this.val val; this.next next;…

ZooKeeper分布式服务与Kafka消息队列+ELKF整合方案

前言 ZooKeeper 是一个分布式的、开放源码的分布式应用程序协调服务&#xff0c;提供配置维护、命名服务、分布式同步、组服务等功能&#xff1b; Kafka 是一个开源的分布式流处理平台&#xff0c;它被设计用来处理实时数据流&#xff0c;包括发布和订阅消息系统、日志收集以…

叉车载货出入库AI检测算法介绍及应用

随着物流行业的快速发展&#xff0c;叉车作为物流运输的重要设备&#xff0c;其安全性和效率性越来越受到人们的关注。然而&#xff0c;在实际操作中&#xff0c;由于人为因素和操作环境的复杂性&#xff0c;叉车事故时有发生&#xff0c;给企业和个人带来了巨大的损失。为了提…

HarmonyOS开发实例:【app帐号管理】

应用帐号管理 介绍 本示例选择应用进行注册/登录&#xff0c;并设置帐号相关信息&#xff0c;简要说明应用帐号管理相关功能。效果图如下&#xff1a; 效果预览 使用说明参考鸿蒙文档&#xff1a;qr23.cn/AKFP8k点击或者转到。 1.首页面选择想要进入的应用&#xff0c;首次进…

JetBrains PhpStorm 2024.1 发布 - 高效智能的 PHP IDE

JetBrains PhpStorm 2024.1 发布 - 高效智能的 PHP IDE 请访问原文链接&#xff1a;JetBrains PhpStorm 2024.1 (macOS, Linux, Windows) - 高效智能的 PHP IDE&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org JetBrains PhpSt…

C语言: 字符串函数(下)

片头 在上一篇中,我们介绍了字符串函数。在这一篇章中&#xff0c;我们将继续学习字符串函数&#xff0c;准备好了吗&#xff1f;开始咯&#xff01; 1.strncpy函数 1.1 strncpy函数的用法 strncpy是C语言中的一个字符串处理函数&#xff0c;它用于将一个字符串的一部分内容…

C++ | Leetcode C++题解之第14题最长公共前缀

题目&#xff1a; 题解&#xff1a; class Solution { public:string longestCommonPrefix(vector<string>& strs) {if (!strs.size()) {return "";}int minLength min_element(strs.begin(), strs.end(), [](const string& s, const string& t)…