一、CZML的来源和介绍
Cesium团队为了描述动态场景专门制定了CZML数据格式,这是一种JSON数据格式,不仅方便交互,而且具有时间属性,其既可以用于绘制各种几何图形,给定颜色、材质、透明度等也可以根据实际的场景需求,放入动态的模型数据,是的场景更加生动。除此以外还可以让CZML中的属性跟随时间变化,如:画面中的小车,给其定义了两个不同时间的位置,通过CZML得差值算法,画面上可以准确地显示车在两个时间点的运动过程。CZML的结构可以更加高效的传输数据,在显示场景之前,不需要加载整个场景数据,可随着时间变化不断加载数据到场景中。
二、CZML数据结构详解
CZML还是一个开放的格式,支持在其基础上进一步扩展功能和特性。下面是一个最基础的CZML数据,它至少要包含两个对象,每一个对象都是一个CZML的数据包。
- 其中第一个对象,是用于声明它是CZML格式,主要在其中填入一些固定的数值。id属性固定是document,name属性值可以根据加载的数据自己命名,version用于设定CZML版本号,暂时只有1.0版本。
- 第二个对象存放的就是场景内的几何模型数据了,每一个几何模型对象都有唯一的id属性用于标识,如果id没有指定,cesium会自动生成一个,但是在后续开发中我们无法对其进行引用,如添加数据等,所以id我们要提前设定好,且在CZML中是唯一的。这里的name属性属于可选配置,可以自定义名称。position用于存放模型位置信息,它定义了一个caetographicDegrees对象,其中三个数据分别设定的是经纬度和高度。box用于指定我们绘制的几何体是盒状的,dimensions存放了尺寸信息,他的cartesuan对象设定了长宽高的数值,material则用于设置几何体的材质颜色。
const czml = [
{
id:"document",
name: "box",
version: "1.0",
},
{
id:"shape1",
name: "Blue box",
position: {
cartographicDegrees: [-114.0,40.0, 300000.0],
},
box: {
dimensions: {
cartesian: [400000.0,300000.0,500000.0],
},
material:{
solidColor: {
color: {
rgba:[0, 0, 255, 255]
}
}
}
}
}
]
三、CZML轨迹数据处理
对比上一个对象,这个对象中加入了clock属性,它用于设定时间相关的数据,更是构建动态轨迹场景必不可少的元素。
- interval设置的是运行的起始时间和结束时间,这里的时间我们使用ISO 8601规范来表示日期和时间,好处:不需要进行时差计算,也不需要换算去协调世界时。
- currentTime设定的是当前的时间节点。
- multiplier设定的是时间的速率,他可以设置沿轨迹运行的速度。
- 第二个对象放入了汽车模型加载的数据model中存放需要加载模型的路径,这里根据模型格式,放在gltf属性中。
- position存放的是模型的位置信息,这些位置信息将自动与clock中设置的时间信息关联起来,使得时刻与坐标点相对应,从而实现动态轨迹效果。
- interpolationAlgorithm设定的是插值算法,他会将各个轨迹点连成一条线,这里绘制的是直线,所以设定为LINEAR。
- forwardExtrapolationType同样用于插值算法,防止出现设定数值超出样本数据范围的情况
- cartesian中放入的是时间、经纬度、高度数据,每四个数据为一组,这里设定了两组数据
- orientation存放的是模型方向信息,还有种更简单的设置方法:可以把unitQuaternion替换成velocityReference,数值设置为#position,Cesium会根据位置信息进行四元数方向转换,从而达到模型在运动时方向转换的效果
"orientation": {
"velocityReference": "#position"
}
- 在第三个对象中,我们绘制了一条行驶轨迹线,polyline表明设置的是线条,position放入的是经纬度和高度信息
- clampToGround设置为true,可以使得生成的线条紧贴地面
// 创建CZML对象
var czml2 = [
{
"id": "document",
"version": "1.0",
"clock": {
"interval": "2018-07-19T15:18:00Z/2018-07-19T15:18:30Z",
"currentTime": "2018-07-19T15:18:00Z",
"multiplier": 5,
"range": "LOOP_STOP",
"step": "SYSTEM_CLOCK_MULTIPLIER"
}
},
{
"id": "CesiumMilkTruck",
"model": {
"gltf": "models/CesiumMilkTruck/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": {
"unitQuaternion": [
0.3084011337938999,
0.3210181022701266,
-0.45850421987074924,
0.7686388857813198
]
}
},
{
"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]
},
"outlineColor": {
"rgba": [0, 0, 0, 255]
},
"outlineWidth": 2
}
},
"width": 10,
"clampToGround": true
}
}
]
四、CZML数据使用方法
首先使用Cesium的dataSources属性加载数据集,因为调用的是CZML数据,这里载入时需要使用CzmlDataSource进行转换,load中即可以放入存储数据的变量,也可以放入文件路径,CZML导入完成后,我们需要对载入后的模型进行操作,就需要使用Promise的then方法,使得数据加之后再调用,将加载的数据作为参数传入
// 加载新地图,设置一个变量用于存储新地图的信息
var esri = new Cesium.ArcGisMapServerImageryProvider({
url:'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
})
Cesium.Ion.defaultAccessToken = '';
const viewer = new Cesium.Viewer('yc-cesiumContainer',{
// 首先要把默认的地图按钮设置为隐藏,否则会影响新地图的加载
baseLayerPicker: false,
// 设置地图
imageryProvider:esri,
shouldAnimate:true, //自动播放
// 放入引入的地形,CesiumTerrainProvider方法是将地形数据,转换为Cesium可以访问的格式
terrainProvider: new Cesium.CesiumTerrainProvider({
// url用于放入地形服务器的地址
url:Cesium.IonResource.fromAssetId(1),
// 可以增加法线,用于提高光照效果
requestVertexNormals:true,
// 可以增加水面特效
requestWaterMask:true
})
});
viewer.dataSources.add(Cesium.CzmlDataSource.load(czml2)).then(function (dataSource){
// 这里我们需要将相机的视口位置设定到载入的模型处
// 使用entities的getById方法可以获取到绑定id的模型数据
// trackedEntity则可以绑定视口位置
viewer.trackedEntity = dataSource.entities.getById('CesiumMilkTruck')
// 如果需要车辆循环行驶播放,要在Cesium初始化时,设置shouldAnimate自动播放属性为true
})