Cesium之快速上手


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.0123.0,55.0120000.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 //持续时间
}));

文章作者: gxl
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 gxl !
 上一篇
数据格式之obj与mtl 数据格式之obj与mtl
这是你自定义的文章摘要内容,如果这个属性有值,文章卡片摘要就显示这段文字,否则程序会自动截取文章的部分内容作为摘要
2018-09-07
本篇 
Cesium之快速上手 Cesium之快速上手
这是你自定义的文章摘要内容,如果这个属性有值,文章卡片摘要就显示这段文字,否则程序会自动截取文章的部分内容作为摘要
2018-09-07