Cesium之CZML数据

640 阅读5分钟

一、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
    })