Cesium 入门
第一节 Cesium主要功能介绍
CesiumJs是目前最流行的三维数字地球渲染引擎。它不仅可以在网页端高效运行,而且还可以借助虚幻引擎在CS端渲染出和游戏一样的高质量效果。免费、开源是其快速普及的重要原因。
目前越来越多的公司选择它作为地理信息系统的基础,成为三维开发程序员的必修功课之一。
Cesium概述
- Cesium是国外一个使用JavaScript编写的基于WebGL的地图引擎。
- Cesium支持3D、2D、2.5D形式的地图展示。
- Cesium可以自行绘制图形,高亮区域。
- Cesium提供良好的触摸支持,且支持绝大多数的浏览器和移动端。
- Cesium功能强大,拥有几百项独立的功能点
Cesium主要功能介绍
- 1.通过CZML创建数据驱动的时间动态场景
- 2.使用WMS、TMS、ESRI等标准绘制影响图层
- 3.具有高分辨率的地形三维,可以清晰地展示各种连绵起伏的山脉
- 4.具有采用KML、GeoJson、TopoJson格式的数据进行矢量绘制的功能
- 5.使用COLLADA和glTF绘制三维模型
- 6.可以调用WebGL的低级地图进行几何体的渲染
- 7.可以在地球上绘制广告牌、标签、文本、折线、多边形等
- 8.通过调整摄像机角度来创建随着时间变化的物体移动路径
- 9.具有点云告诉渲染的功能
- 10.动态调整地球色调与亮度对比度
- 11.具有热力图功能
- 12.具有地形等高线与等高线自定义颜色功能
- 13.具有在地球上绘制柱状图的功能
第二节 Cesium官网简析
Cesium官网地址 https://cesium.com/
Cesium ion
- Cesium ion,指使用Cesium的用户,是发现3D内容和平铺数据进行流式传输的中心。
- 免费注册一个免费帐户,以获得使用离子的必应地图的全球图像,和Cesium世界地形资产所需的访问令牌。
文档中心
- API
HellowWorld
- 一个简短的cesium程序
Cesium Viewer 查看器
- Cesium查看器,浏览地球并从各种图形和地形图层中进行选择,以及加载CZML、GeoJson、和Cesium支持的其他格式。
Sandcastle 示例库
- Cesium的实时代码编辑器和示例库,浏览Cesium API功能的示例,并在浏览器中编辑和运行。在其中创建和Cesium应用程序可以保存和下载。
RunTest
- Cesium的全套单元测试程序
Links 常用的外部链接
- Cesium官网、博客、入门指南、交流社区、Github代码仓库
- 用户故事:分享的使用CesiumSDK开发的Demo和工程
- WebGL Report:对当前浏览器WebGL兼容测试的报告
第三节 Cesium源码目录
Apps 目录
- Cesium Viewer 查看器
- Sample Data 样例的本地数据
- Sandcastle 演示程序
- TimelineDemo 时间轴页面
Build 目录
- Cesium 打包压缩后的最小版本的Cesium库
- CesiumUnminifiled 正常源代码
- Documentation每个函数对应的html文档页面
Source 源码目录
- Core 内核代码文件
- Assets 资产目录,存放了内置的渲染素材,具体有地球坐标系转换所需要的计算,由28个json文件组成,图标文件,天空纹理图片
- DataSources 数据源目录
- Renderer 渲染目录,存放2D、3D、2.5D渲染的代码文件
- Scene 场景目录,存放场景管理涉及的文件
- Shaders 存放各种与着色器有关的代码文件
- ThirdParty 第三方库目录,存放所有用到的第三方开源文件
- Widgets UI元件目录,包含了UI元素有关的所有文件
- Workers 线程目录,Cesium采用Web、Workers机制来实现多线程处理,从而加快执行速度
- WorkersES6 ES6版本的线程目录,加快执行速度
第四节 地球初始化
<script src="../../libs/Cesium/Cesium.js"></script>
<link href="../../libs/Cesium/Widgets/widgets.css" rel="stylesheet">
<style>
html,body {
margin: 0px;
padding: 0px;
}
</style>
<div id="puiedu-cesiumContainer"></div>
<script>
Cesium.Ion.defaultAccessToken = 'yourToken';
const viewer = new Cesium.Viewer('puiedu-cesiumContainer');
</script>
第五节 Cesium查看器、场景、实体、数据源
Cesium四个重要的类
- Viewer查看器类、Scene场景类、Entity实体类、DataSourceCollection数据源集合类
1.Viewer查看器类
- Viewer查看器类是Cesium展示三维要素内容的主要窗口,它不仅仅包含三维地球的视窗,还包括了一些基础控件,在定义Viewer对象的同时需要设定基础部件、图层等初始化状态。
Viewer创建语句
- new Cesium.Viewer(cesiumContainer,option)
- 参数1:用于指定地图主窗口div的id
- 参数2:可选设置参数,包括图形、地形、时间系统等参数,种类多样
const viewer = new Cesium.Viewer('puiedu-cesiumContainer',{
animation:false, // 时间轴上的动画播放部件
timeline:false // 时间轴
});
const entity = viewer.entities.add({
position:Cesium.Cartesian3.fromDegrees(116.39,39.91,400),
point:{
pixelSize:100,
color:new Cesium.Color(0,1,0,1)
}
})
viewer.trackedEntity = entity;
2.Scene场景类
- 在Cesium中Scene是非常重要的类,是所有3D图形对象的容器,是在Viewer内部隐式创建的,可以对基础地理环境进行设置,包括地图、地形等。控制光照强度,绘制点线面等。注意:在viewer中设置图层,等价于在scene中设置图层。
- 还可以对场景数据进行设置,Cesium底层空间数据绘制的方法是依赖Primitive,Primitive API功能强大而且灵活,为绘制高级地形提供了很大的自由度。
- Scene还可以对场景进行交互,如鼠标事件,相机事件等。如:可以通过scene控制相机对视口进行切换,使用相机的setView方法,设置经纬度、高度
viewer.scene.globe.show = true; // 地球的显示隐藏
console.log(viewer.imgerLaters == viewer.scene.imgerLaters); // true
viewer.scene.camera.setView({
destination:Cesium.Cartesian3.fromDegrees(116.39,39.9,2000)
})
3.Entity实体类
Entity是由Primitive封装而来,但是Entity并不属于Scene。相较而言,Entity封装程度高,构造简单,使用便捷,是开发者专注数据的呈现,而不必担心底层的可视化机制。它还提供了用于构建复杂的、事件动态可视化的结构,与静态数据自然结合。Entity API能够提供灵活的、高性能的可视化,同时提供易于使用的接口。
Entity在使用中主要用于加载实体模型,几何图形,对其进行样式设置,动态修改等。
const entity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(116.39, 39.91, 400),
point: {
pixelSize: 100,
color: new Cesium.Color(0, 1, 0, 1) //绿色
}
})
viewer.trackedEntity = entity; // 将摄像头设置到原点处,便于观测
4.DataSourceCollection数据源集合类
DataSourceCollection是Cesium中加载矢量数据的主要方式之一。最大的特点是支持加载矢量数据集合和外部文件的调用,主要有三种调用方法:CzmlDataSource、KmlDataSource、GeoJsonDataSource,分别对应加载czml、kml、GeoJson文件。加载矢量数据必不可少,将矢量数据转换为这三种任意一种格式,便可以在Cesium中实现矢量数据的加载和存取。
dataSources用于将任意数据转换为EntityCollection,此处调用GeoJSON格式数据,加载图层。
viewer.dataSources.add(
Cesium.GeoJsonDataSource.load("url根路径src/...")
)
第六节 Cesium的坐标与转换
Cesium具有真实地理坐标的三维球体,用户通过二维屏幕与Cesium进行操作,把三维模型绘制在三维球体上,就需要在地理坐标与屏幕坐标之间进行换算。
Cesium主要有5种坐标系统:
- 1.WGS84经纬度坐标系(没有实际对象)
- 2.WGS84弧度坐标系(Cartographic)
- 3.笛卡尔空间直角坐标系(Cartographic3)
- 4.平面直角坐标系(Cartographic2)
- 5.4D笛卡尔坐标系(Cartographic4)
坐标介绍
1.WGS84经纬度坐标系(没有实际对象)
- 以地心为中心,经度-180到180,纬度-90到90
2.WGS84弧度坐标系(Cartographic)
- 构建Cartographic对象类: new Cesium.cartographic(longitude,latitude,height)
- 函数内部弧度计算:弧度 = Π/180 * 经纬度
3.笛卡尔空间直角坐标系(Cartographic3)
- 构建Cartographic3对象类: new Cesium.Cartesian3(x,y,z)
4.平面直角坐标系(Cartographic2)
- 构建Cartographic2对象类: new Cesium.Cartesian2(x,y)
坐标转换
1.经纬度与弧度的转换
- 经纬度转弧度 let radians = Cesium.CesiumMath.toRadians(degrees)
- 弧度转经纬度 let degrees = Cesium.CesiumMath.toDegrees(radians)
2.WGS84经纬度坐标和WGS84弧度坐标(Cartographic)的转换
- 构建WGS84弧度坐标-构造函数法:
new Cesium.Cartographic(longitude弧度,latitude弧度,height高度)
- 构建WGS84弧度坐标-静态函数法:
var cartographic = Cesium.Cartographic.fromDegrees(longitude弧度,latitude弧度,height高度)
var cartographic = Cesium.Cartographic.fromRadians(longitude弧度,latitude弧度,height高度)
3.WGS84转为笛卡尔空间直角坐标系
- 通过经纬度进行转换
var cartesian3 = Cesium.Cartesian3.fromDegrees(longitude弧度,latitude弧度,height高度)
var cartesian3 = Cesium.Cartesian3.fromDegreesArray(coordinates)
corrdinates格式为不带高度的数组,如:[-278.0,66.0,123.0,55.0]
var cartesian3 = Cesium.Cartesian3.fromDegreesArrayHeights(coordinates)
corrdinates格式为带有高度的数组,如:[-278.0,66.0,6000.0,123.0,55.0,120000.0]
- 间接转换
var wgs84 = Cesium.Cartographic.fromDegrees(longitude弧度,latitude弧度,height高度)
var wgs84 = Cesium.Cartographic.fromRadians(longitude弧度,latitude弧度,height高度)
var cartesian3 = Cesium.Ellipsolid.WGS84.cartographicToCartesian(wgs84)
var cartesian3 = Cesium.Ellipsolid.WGS84.cartographicToCartesianArray([wgs84_1,wgs84_2,wgs84_3])
4.笛卡尔空间直角坐标系转换为WGS84
var cartographic = Cesium.Cartographic.fromCartesian(cartesian3)
var cartographic = Cesium.Ellipsolid.WGS84.cartesianToCartographic(cartesian3)
var cartographic = Cesium.Ellipsolid.WGS84.cartesianToCartographicArray([cartesian1,cartesian2,cartesian3])
5.屏幕坐标转场景WGS84坐标
var cartesian3 = viewer.scene.pickPosition(Cartesian2)
6.屏幕坐标转地表坐标
var cartesian3 = viewer.scene.globe.pick(viewer.camera.getPickRay(Cartesian2).viewer.scene)
// 这里是地球表面的WGS84坐标,包括地形,不报错模型、倾斜摄影表面
7.屏幕坐标转椭球面坐标
var cartesian3 = viewer.scene.camera.pickEllipsoid(Cartesian2)
// 这里的椭球面坐标是参考椭球的WGS84坐标,不包含地形、模型、倾斜摄影表面
8.笛卡尔空间直角坐标系转平面坐标系
var cartesian2 = Cesium.SceneTransfroms.wgs84ToWindowCoodinates(viewer.scene,cartesian3)
第七节 相机系统
三维中需要确定视点位置和视线方向。使用相机就是为了控制场景中的视域。拖动地球的时候,地球是不动的,只是相机在移动,产生场景移动的效果。Cesium设定了默认的鼠标事件,用于和我们的相机系统进行交互。Cesium 相机系统方法: setView、flyTo、lookAt、viewBoundingSphere,以及其他API。
设置相机方向和高度的方法 Cesium.HeadingPitchRange(heading,pitch,range))
//Cesium 相机系统 setView flyTo lookAt
const position = Cesium.Cartesian3.fromDegrees(116.39, 39.91, 400); //飞行目的地
// setView 没有动画,适用于快速切换视角
viewer.camera.setView({
destination: position, // 设定相机的目的地
orientation: { // 相机视口的方向
heading: Cesium.Math.toRadians(0), // 水平旋转,围绕Y轴,0为正北方向
pitch: Cesium.Math.toRadians(-90), // 上下旋转,围绕X轴,-90为俯视地面
roll: 0 // 视口的翻滚角度,围绕Z轴,0为不翻转
}
})
// flyTo具有空中飞行逐步切换视域的效果,可以设置飞行时间
viewer.camera.flyTo({
destination: position,
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-90),
roll: 0
},
duration: 5, // 飞行时间
})
// lookAt直接将视角跳转到目的地,旋转视角不会离开center位置,用于锁定某个场景的视角
const center = Cesium.Cartesian3.fromDegrees(116.39, 39.91); // 目的地位置
const heading = Cesium.Math.toRadians(50);
const pitch = Cesium.Math.toRadians(-90);
const range = 2500; // 高度
viewer.camera.lookAt(center, new Cesium.HeadingPitchRange(heading, pitch, range));// 设置相机方向和高度的方法
viewBoundingSphere方法设置中心观测点
viewBoundingSphere方法,视角切换效果同setView,没有飞行效果,直接到目的地,但是它可以给定一个指定的目标点,使用户可以从多个角度更好的观测。如:将目标点设置在飞机中心,并给一定的观察距离,即可从各个角度观测到物体的样式和状态。可以用于对建筑物进行定点观测。
// 目标位置 笛卡尔坐标
const position = Cesium.Cartesian3.fromDegrees(116.39, 39.91, 1500);
// 变量存储模型的朝向
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, new Cesium.HeadingPitchRoll(-90, 0, 0));
// entity加载模型
var entity = viewer.entities.add({
position: position,
orientation: orientation,
model: {
uri: "../../libs/models/Cesium_Air.glb", // 模型地址
minimumPixelSize: 100, // 最小大小
maximumScale: 10000, // 缩放最大比例
show: true // 模型的显示
}
});
// viewBoundingSphere
// 参数1:视点的位置 new Cesium.BoundingSphere(position,20)
// 参数2:相机的朝向 new Cesium.HeadingPitchRange(0,0,0)
viewer.camera.viewBoundingSphere(new Cesium.BoundingSphere(position, 20), new Cesium.HeadingPitchRange(0, 0, 0));
第八节 地图、地形加载
以下示例代码展示地图、地形加载。很多地图的加载和访问需要在官方添加权限。
// 加载地图 存储新地图 使用ArcGis地图服务 Cesium配置的相关你方法
var esri = new Cesium.ArcGisMapServerImageryProvider({
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
})
Cesium.Ion.defaultAccessToken = 'yourToken';
const viewer = new Cesium.Viewer('puiedu-cesiumContainer', {
baseLayerPicker: false, // 隐藏默认地图
// imageryProvider:esri, // 设置地图
terrainProvider: new Cesium.CesiumTerrainProvider({ // 设置地形,转换为可以访问的格式
url: Cesium.IonResource.fromAssetId(1), // 地形服务器的地址
requestVertexNormals: true, // 增加法线,提高光照效果
requestWaterMask: true // 水面效果
})
});
// 夜晚的地球 直接粘贴 设置地图图层 添加新图层
var layer = viewer.imageryLayers.addImageryProvider(
new Cesium.IonImageryProvider({ assetId: 3812 }) // 通过id指向Cesium提供的资产包
);
第九节 建筑的添加和使用
以下示例代码展示建筑物的添加、样式的修改。
var esri = new Cesium.ArcGisMapServerImageryProvider({
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
})
Cesium.Ion.defaultAccessToken = 'yourToken';
const viewer = new Cesium.Viewer('puiedu-cesiumContainer', {
baseLayerPicker: false,
imageryProvider: esri,
terrainProvider: new Cesium.CesiumTerrainProvider({
url: Cesium.IonResource.fromAssetId(1),
requestVertexNormals: true,
requestWaterMask: true
})
});
// 添加建筑物 个人资产中添加buildings
// scene容器中设置primitives属性 获取大量的基元集合 使用add方法加载数据
// var tileset = viewer.scene.primitives.add(
// new Cesium.Cesium3DTileset({ // Cesium用于传输海量异构3D地理空间数据集
// url: Cesium.IonResource.fromAssetId(96188) // 绑定id数据
// })
// )
// 添加建筑物 个人资产中添加buildings (这个建筑物具有高度属性)
var tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: Cesium.IonResource.fromAssetId(75343),
})
);
// 添加相机信息 改变视口效果
viewer.camera.setView({
destination: new Cesium.Cartesian3(1333597.291762958, -4667718.246269587, 4147626.344790953),
orientation: {
heading: 0.8384333942956657,
pitch: -1.299766516859664,
roll: 0.0
}
});
// 设置建筑物的样式 后续还可以添加建筑物的名称和相关信息,划分区域
tileset.style = new Cesium.Cesium3DTileStyle({ // 颜色设置方法
color: {
conditions: [
['${Height} >= 300', 'rgba(45,0,75,0.5)'],
['${Height} >= 200', 'rgb(102, 71, 151)'],
['${Height} >= 100', 'rgb(170, 162, 204)'],
['${Height} >= 50', 'rgb(224, 226, 238)'],
['${Height} >= 25', 'rgb(252, 230, 200)'],
['${Height} >= 10', 'rgb(248, 176, 87)'],
['${Height} >= 5', 'rgb(198, 106, 11)'],
['true', 'rgb(127, 59, 8)']
]
},
show: '${Height} >= 0' // 高度大于0的才能显示
})
第十节 空间数据加载
空间数据包括矢量数据和栅格数据,之前的地图、地形为栅格数据。矢量数据包括 点线面几何体,模型、标签等。
var esri = new Cesium.ArcGisMapServerImageryProvider({
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
})
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkZDIzMmYwMy1hYTlmLTQxZWItODAyYy03MjAyMTc4YzVjOGYiLCJpZCI6NTc4MTAsImlhdCI6MTY0MTk2NjA2Nn0.ACfm4kMsXv_o3brMajCyqkORvh_6llBXF2BmD6UpRyw';
const viewer = new Cesium.Viewer('puiedu-cesiumContainer', {
baseLayerPicker: false,
imageryProvider: esri,
terrainProvider: new Cesium.CesiumTerrainProvider({
url: Cesium.IonResource.fromAssetId(1),
requestVertexNormals: true,
requestWaterMask: true
})
});
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(116.39, 39.91, 2500.0),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-90.0),
roll: 0.0
}
});
// 加载 几何体或模型 都是基于 空间位置的
// 空间数据加载 之前的为栅格数据 矢量数据包括几何体的加载,模型、标签等
var position = new Cesium.Cartesian3.fromDegrees(116.39, 39.91, 0);
// 加载圆点
const entity = viewer.entities.add({
position: position,
point: { //圆点
pixelSize: 100,
color: new Cesium.Color(1, 0, 0, 1)
}
})
// 加载直线
const entity = viewer.entities.add({
polyline: {
show: true,
// 位置添加集合
positions: new Cesium.Cartesian3.fromDegreesArray([116.39, 39.91, 116.40, 39.91]),
width: 5,
material: new Cesium.Color(0, 0, 1, 1)
}
})
// 加载 面
const entity = viewer.entities.add({
position: position,
plane: { //用于绘制面
plane: new Cesium.Plane(Cesium.Cartesian3.UNIT_Z, 0.0), // 轴向 沿着Z轴平铺
dimensions: new Cesium.Cartesian2(400, 300), // 长度 宽度
material: Cesium.Color.RED.withAlpha(0.5), // 红色 透明度0.5
outline: true, // 边框
outlineColor: Cesium.Color.BLACK // 边框颜色
},
})
// 加载飞机模型
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, new Cesium.HeadingPitchRoll(-90, 0, 0));
var entity = viewer.entities.add({
position: position,
orientation: orientation,
model: {
uri: "../../libs/models/Cesium_Air.glb",
minimumPixelSize: 100,
maximumScale: 10000,
show: true
}
});
viewer.trackedEntity = entity;
// 加载标签 文字始终朝向屏幕 缩放不影响字体大小
const entity = viewer.entities.add({
position: position,
label: {
text: "动力IT实训",
font: "50px Helvetica", // 字体和大小
fillColor: Cesium.Color.SKYBLUE, // 文字颜色
},
})
第十一节 空间数据管理
// 添加三角形
var redPolygon = viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([116.39, 39.91, 116.39, 39.915, 116.395, 39.91]),
material: Cesium.Color.RED,
extrudedHeight: 200 //高度
}
})
// 设置更多样式
const entity = viewer.entities.add({
position: new Cesium.Cartesian3.fromDegrees(116.39, 39.91, 0),
plane: {
plane: new Cesium.Plane(Cesium.Cartesian3.UNIT_Z, 0.0),
dimensions: new Cesium.Cartesian2(400, 300),
material: "../../libs/image/dlitsx.png",
outline: true,
outlineColor: Cesium.Color.BLACK,
},
})
// 删除 修改样式
viewer.entities.remove(yellowPolygon);
viewer.entities.getById('BlueModel').polygon.material = Cesium.Color.RED;
viewer.entities.removeAll()
第十二节 鼠标交互 数据查询
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
let pick = viewer.scene.pick(movement.position);
if (Cesium.defined(pick) && pick.id) {
//alert("鼠标左键点击事件");
console.log(JSON.parse(pick.id));
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// 其他事件
// scene.pick scene.drillpick Globe.pick
// Cesium.ScreenSpaceEventType.MIDDLE_CLICK
// Cesium.ScreenSpaceEventType.MOUSE_MOVE
// Cesium.ScreenSpaceEventType.RIGHT_CLICK
第十三节 三维数据格式 3DTiles
3DTiles的来源和介绍
3D Tiles是Cesium于2016年3月定义的一种三维模型瓦片数据结构,它将海量的三维数据用分块、分层的形式组织起来,很大程度上减轻了浏览器的负担。
如:纽约城市模型加载了约110万座建筑物,并根据建筑物的区域和高度用颜色进行划分,除此之外还提供了细节层次的LOD功能,在远观时,降低模型的面数和精度,拉近后再将细节加载出来,大大增强了页面的加载速度,更可以用于跨桌面使用,使web端和移动应用端应用程序共享。
主要用于静态场景。
数据格式的详细介绍请查看3DTiles文件。
3DTiles的数据特点
1.开放式的数据规范
可以根据实际需求设定三维模型的大小和范围,还能适配多种空间分区方案,如普通网格、四叉树、八叉树等。
四叉树:是一种树形数据结构,它的每个节点下至多可以有四个子节点,通常把二维空间细分为四个区域,并把该区域里的相关信息存入到四叉树节点中。四叉树的每一个节点代表一个矩形区域,每一个矩形区域又可划分为四个小矩形区域。
八叉树:将场景从二维空间延伸到了三维空间,树中的子节点只会有八个或者零个,每一个节点同样用于存储数据。
2.异质性支持
可以将不同类型的三维模型数据,如:普通模型数据加 倾斜摄影数据 加自绘几何数据 放在一起,转化为统一标准的数据集,让它们可以再同一场景下显示出来。
3.专门为三维可视化设计的
并在其中引入了图形领域的技术,在不满足特定条件的情况下,并不会对场景内的模型做整个渲染,而是只会渲染轮廓,大大降低了计算量,使得浏览器请求到数据以后,渲染的流程也更加简单,同时,因为三维模型预先处理成了分块的三维瓦片格式,所以也减少了webgl绘制请求的数量。
4.可交互性
支持对加载模型的拾取和样式修改,大量加载以后,可以对其中的单独模型进行交互,如:高亮显示鼠标处的模型、或进行删除等,也可根据建筑模型的高度和年代,设置不同的显示效果而不需要重新更新代码。
3DTiles的代码构成
两个部分组成:
1.组分一:json格式的数据
asset:包含整体tileset元素属性的对象
version:定义3DTiles版本的字符串
tilesetVersion:用于定义特定应用中的版本号,可选项
geometricError:定义了一个非误差单位,低于这个误差值,瓦片不会被渲染,单位 米
root:用于定义根瓦片
transform:可选项,作用是在加载大量模型或者建筑物的情况下,单个模型的点云瓦片集能在自己的坐标系中定义,其内的数据是一个4x4的仿射变换矩阵,以列主序存储,用来实现从瓦片局部坐标系到父瓦片或根瓦片坐标系的变换。
geometricError:当前瓦片集被渲染的误差。
content:通过url引入文件(b3dm),这里引入的文件就是瓦片的内容,它的数据是二进制的,其支持的二进制格式有.b3dm .i3dm .pnts等,甚至可以在其中再放入一个3DTiles文件,不能引用自己。
refine:定义LOD细化的方法,简单来说就是瓦片是如何切换的。
children:因为3DTiles是分级别的,多以每个Tile还会有子Tile、子子Tile。
2.组分二:引用的瓦片数据文件 用于渲染数据的文件。
.b3dm格式瓦片集 主要用于加载批量的模型。
.pnts格式瓦片集 用于加载点云数据模型。
.cmpt格式瓦片集 允许一个cmpt文件内嵌多个其他类型的瓦片。
// 加载3DTiles数据
var tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({ // 用于实例化
url: "../../libs/TilesetWithDiscreteLOD/tileset.json",
maximumScreenSpaceError: 2, //最大的屏幕空间误差,越低越好
maximumNumberOfLoadedTiles: 1000, //最大加载瓦片个数,用于给定一定的限制,防止数据量过大,占用内存过高
})
);
json格式的数据 tilest.json
{
"asset": {
"version": "1.0"
},
"geometricError": 500,
"root": {
"transform": [
96.86356343768793,
24.848542777253734,
0,
0,
-15.986465724980844,
62.317780594908875,
76.5566922962899,
0,
19.02322243409411,
-74.15554020821229,
64.3356267137516,
0,
1215107.7612304366,
-4736682.902037748,
4081926.095098698,
1
],
"boundingVolume": {
"box": [
0,
0,
0,
7.0955,
0,
0,
0,
3.1405,
0,
0,
0,
5.0375
]
},
"geometricError": 100,
"refine": "REPLACE",
"content": {
"url": "dragon_low.b3dm"
},
"children": [
{
"boundingVolume": {
"box": [
0,
0,
0,
7.0955,
0,
0,
0,
3.1405,
0,
0,
0,
5.0375
]
},
"geometricError": 10,
"content": {
"url": "dragon_medium.b3dm"
},
"children": [
{
"boundingVolume": {
"box": [
0,
0,
0,
7.0955,
0,
0,
0,
3.1405,
0,
0,
0,
5.0375
]
},
"geometricError": 0,
"content": {
"url": "dragon_high.b3dm"
}
}
]
}
]
}
}
第十四节 动态数据格式 CZML
CZML的来源和介绍
CZML是cesium团队专门为动态场景制定的数据格式。它是一种json数据格式,不仅方便交互,而且具有事件属性。既可以用来绘制各种几何图形,给定颜色、材质、透明度等,也可以根据实际需求,放入动态的模型数据,使得场景更加生动。
除此之外,还可以让CZML中的属性跟随时间变化,如:给小车定义不同时间的两个位置,通过CZML的插值算法,画面上可以准确显示车再两个时间点的运动过程。
CZML的结构可以更加高效的传输数据,在显示场景之前,不需要加载整个场景数据,可随着时间变化不断加载数据到场景中。如示例所示,整个场景数据都会跟随小车的形式不断加载。
CZML还是一个开放的格式,支持在其基础上进一步扩展功能和特性。
CZML的基础代码结构
1.至少包含两个对象,每个对象都是CZML的数据包。
第一个对象是用来声明它是CZML格式,主要在其中填入一些固定的数值,id固定为document,name自定义,version版本号1.0。
第二个对象存放场景内的几何模型数据,每一个几何模型对象都有唯一的id属性用于标识,如果id没有指定,cesium会自动生成一个,但是后续开发中将无法禁用、添加数据等,name可选。
position用于存放模型的位置信息,里面定义了一个cartographicDegrees对象,其中设定经纬度、高度。
box用于指定绘制盒状的,dimensions存放了尺寸信息,它的cartesian对象设定了长宽高的数值,material用于设置几何体的材质颜色。
2.设置动态的行驶轨迹
在第一个对象中加入clock属性,用于设定时间相关的数据,是构建动态轨迹必不可少的元素。
interval:起始时间和结束时间 ISO8601规范 不需要进行时差计算
currentTime:当前时间节点
multiplier:时间的速率,设置沿轨迹运行的速度
3.第二个模型放置了汽车模型的数据
唯一id,model的gltf属性中,存放模型的路径 .glb文件
position里存放模型的位置信息,将自动于clock里设置的时间信息关联,使时刻与坐标点对应,从而实现动态轨迹效果,interpolationAlgorithm设置插值算法,直线,forwardExtrapolationType设置防止出现设定数值超出样本数据范围,cartesian放置了两组时间,经纬度,高度。
orientation存放模型的方向信息,”velocityReference”: “#position”,cesium会根据位置信息进行四元方向转换,从而达到行驶转向效果。
第三个对象,绘制轨迹线,polyline线条,clampToGround紧贴地面。
4.加载数据集viewer.dataSources.add
数据转换Cesium.CzmlDataSource.load(czml),放文件变量或路径。
进行操作Promise.then,在回调函数中设置相机视口。
5.自动循环播放,在初始化时设置shouldAnimate:true
var czml = [{
"id": "document",
"name": "myname",
"version": "1.0",
"clock": {
"interval": "2018-07-19T15:18:00Z/2018-07-19T15:18:30Z",
"currentTime": "2018-07-19T15:18:00Z",
"multiplier": 5,
}
},
{
"id": "CesiumMilkTruck",
"model": {
"gltf": "../../libs/models/CesiumMilkTruck.glb",
},
"position": {
"interpolationAlgorithm": "LINEAR",
"forwardExtrapolationType": "HOLD",
"cartesian": [
"2018-07-19T15:18:00Z",
1216348.1632364073,
-4736348.958775471,
4081284.5528982095,
"2018-07-19T15:18:30Z",
1216369.1229444197,
-4736377.467107148,
4081240.888485707
],
},
"orientation": {
"velocityReference": "#position"
},
},
{
"id": "Polyline",
"polyline": {
"positions": {
"cartesian": [
1216348.1632364073,
-4736348.958775471,
4081284.5528982095,
1216369.1229444197,
-4736377.467107148,
4081240.888485707
]
},
"material": {
"polylineOutline": {
"color": {
"rgba": [255, 255, 0, 255]
},
}
},
"width": 10,
"clampToGround": true
}
}];
viewer.dataSources.add(Cesium.CzmlDataSource.load(czml)).then(function (dataSource) {
viewer.trackedEntity = dataSource.entities.getById('CesiumMilkTruck')
})
第十五节 时间系统 粒子系统
时间系统
时间系统在动态数据可视化发挥了重要的作用,在三维场景的基础上增加了时间维度信息,比如初始化时自带时间控件,默认显示当前时间。时间控件Clock有两部分组成,animation控件控制时间的启动和暂停;timeline控制时间线。
viewer.clock.shouldAnimate = true; // 初始化页面自动循环播放
viewer.clock.multiplier = 1; // 时间速率
let start = Cesium.JulianDate.fromIso8601('2022-01-05'); //当前时间
let end = Cesium.JulianDate.fromIso8601('2022-01-20'); // 结束时间
viewer.timeline.zoomTo(start, end); //设置到时间线
粒子系统
火焰粒子特效:先设置粒子样式,再通过粒子发射器发射粒子,控制粒子再一定时间内存在、消亡,并且使得粒子可以随着时间的推移,改变外观和行为。如果加载的时粒子类数据,就需要使用primitives加载数据,因为其更接近底层的图形开发。
// 火焰粒子特效
viewer.scene.primitives.add(new Cesium.ParticleSystem({
image: '../../libs/SampleData/fire.png',
imageSize: new Cesium.Cartesian2(20, 20),
startScale: 1.0,//初始大小
endScale: 4.0,//结束大小
particleLife: 1.0,//每个粒子存在时间
speed: 5.0,//发射粒子速度
emitter: new Cesium.CircleEmitter(0.5),//各种 发射器 半径
emissionRate: 5.0,//每秒发射的离子数量
// 粒子系统的位置 模型转换为世界坐标的4x4矩阵 绑定到飞机上
modelMatrix: entity.computeModelMatrix(viewer.clock.startTime, new Cesium.Matrix4()),
lifetime: 16.0 //持续时间
}));