CesiumLanguage(CZML)入门--(一)罗松与拇指翻译整理luosong01230123@Hotmail.com2014-07-30北京CZML是一种用来描述动态场景的JSON架构的语言,主要用于Cesium在浏览器中的展示。它可以用来描述点、线、布告板、模型以及其他的图元,同时定义他们是怎样随时间变化的。Cesium拥有一套富客户端API,通过CZML采用数据驱动的方式,不用写代码我就可以使用通用的Cesiumviewer构建出丰富的场景。Cesium与CZML的关系就如同GoogleEarth和KML的关系。CZML和KML都是用来描述场景的数据格式,可以通到很多其他的程序自动生成,或者手写也可以。CZML拥有很多的特性,其中有一些区别于KML的:1.CZML是基于JSON的。2.CZML可以准确的描述值随时间变化的属性。理由,一条在某一时间内是红色的而在另一时间内是蓝色的。同时客户端可以根据时间戳进行差值。加入有一辆车,分别定义了两个不同时间的位置,通过CZML定义的差值算法,客户端可以准确的显示在这两个时间点之间车的位置。所有属性都可以是随时间变化的。3.CZML通过增量流的方式传送到客户端。在场景显示之前,整个CZML文档需要首先被下载到客户端。在某些情况下,个别客户端可能会加入或离开正在传输的流。(这段翻译的不好)4.CZML高度优化,旨在解析时更紧凑也更容易,让人工的读写更容易。5.CZML可扩展,尽管CZML的主要作用在与虚拟地球客户端程序与场景的交流,但它可以很容易的通过扩展来满足其他一些辅助的程序对静态或动态数据的需求。例如,随时间动态变化在数据就可以用在某些2D的图表程序中。6.CZML是一个开放的格式。我们希望有更多的程序能使用CZML,同时期待有一天它也能成为OGC一样的标准。7.可以通过czml-writer来生成CZML,这个程序维护在Github上。我们将CZML标准已经它的相应实现分为4个部分:CZMLStructure--CZML文档的整体结构CZMLContent--内容CZMLinCesium--Cesium中解析和显示CZML的流程czml-writer-Architecture–czml-writer的架构CZMLStructureCZML是json的一个子集,也就是说一个有效的CZML文档同时也是一个有效的JSON文档。特别的,一个CZML文档包含一个JSON数组,数组中个每一个对象都是一个CZML数据包(packet),一个packet对应一个场景中的对象,例如一个飞机。Note:在下面的例子中我们使用javascript方式的注释来帮助理解CZML,但在真实场景中是不允许的。[//packetone{id:GroundControlStationposition:{cartographicDegrees:[-75.5,40.0,0.0]},point:{color:{rgba:[0,0,255,255]},}},//packettwo{id:PredatorUAV,//...}]每个packet都有一个id属性用来标示我们当前描述的对象。IDsdonotneedtobeGUIDs-URIsmakegoodIDs-(不知道怎么翻译),但是在同一个CZML以及与它载入同一个范围(scope)内的其他CZML文件中必须是唯一的。随后我们将讨论scope的含义。假如没有指定id,那么客户端将自动生成一个唯一的id。但是这样的话在随后的包中我们就没有办法引用它了,例如我们不能再往它里面添加数据。除了id以为,一个包通常还包含0到多个(正常情况下是1到多个)定义对象图形特征的属性。正如上面的例子,我们定义了一个“GroundControlStation”对象,它拥有一个固定的经度-75.0维度40.0的WGS84坐标,高度为0,随后一个蓝色的点将会绘制在他的坐标位置处。CZML还有很多标准的属性,包括用来添加点、布告板、模型、线以及其他图形到场景的属性。所有这些属性将在CZMLContent这节讨论。在这里我们主要讨论这些数据是怎样组织的。例如,我们怎样定义一个属性,使它在两个不同的时间拥有两个不同的值。时间间隔Intervals通常情况下CZML的属性值是一个数组,数组中的每个元素对应每一个不同的时间,属性的值。时间间隔的定义使用interval属性,通过ISO8601interval格式的字面值表示。{id:myObject,someProperty:[{interval:2012-04-30T12:00:00Z/13:00:00Z,number:5},{interval:2012-04-30T13:00:00Z/14:00:00Z,number:6},]}这里我们定义了一个someProperty属性,它有两个时间间隔,第一个是从中午到下午一点,属性值为5,第二个是从下午一点到下午两点,属性值为6,在时间由第一个间隔变化到第二个间隔的时候,属性值会瞬间从5变到6。注意,这里的时间为UTC(协调世界时),而我们国家通常使用的是UTC+8也就是北京时间,所以要注意。我们使用number来表示属性是一个数字类型的属性。值得注意的是有些属性允许通过不同的格式来定义,例如表示表示位置的属性可以通过笛卡儿坐标的X、Y、Z表示,也可以通过经纬度和高程来表示。CZMLContent一节将会详细讨论。Interval属性是可选的,你可以定义也可以不定义,如果没有定义,默认为整个时间。通常定义多个无限的时间间隔或者间隔之间有重叠是没什么意思的,如果你非要这么做,那么在CZML中最后定义的时间间隔将拥有较高的优先级。通常情况下属性值只跨越一个时间间隔,这时候你间隔列表可以省略。{id:myObject,someProperty:{interval:2012-04-30T12:00:00Z/14:00:00Z,number:5}}和之前的一样,加入interval跨越整个时间,那么你可以省略掉它。对于一些简单的值,例如上面我们使用的数字类型,加入它对于整个时间来说都不变,那么我还可以定义的更简单一些。{id:myObject,someProperty:5}这种简略的表示法,适用于所有值是简单的json数据类型(string、number、boolean)的的属性。复合值CompositeValues一些复杂的值复合值例如笛卡尔坐标位置或颜色,是通过json数组的形式来表示。例如坐标位置,所使用的数组有三个元素,分别对应于坐标的x、y和z。{id:myObject,someComplexProperty:{cartesian:[1.0,2.0,3.0]}}合成值必须定义在间隔中,即使他的时间间隔是无限的也是一样,不能采用简略的写法。假如允许值[1.0,2.0,3.0]直接作为someComplexProperty的属性值,那么客户端代码就需要解析CZML并且判断数组里面的值到底是时间间隔列表(intervalslist)还是说是简单的值。为了简单起见,我们不允许这样的写法。属性值采样SampledPropertyValues到目前为止我们讨论的了怎样为那些横跨整个时间的的属性定义单一的值,以及针对离散的时间间隔定义不同的值。一些属性(CZMLContent一节将告诉你是那些)允许你定义时间戳采样,客户端通过给定的时间差值计算出属性的值。时间的定义是采用ISO8601标准字符串。{//...someInterpolatableProperty:{cartesian:[2012-04-30T12:00Z,1.0,2.0,3.0,2012-04-30T12:01Z,4.0,5.0,6.0,2012-04-30T12:02Z,7.0,8.0,9.0]}}在这里我们指定在中午的时候属性值为[1.0,2.0,3.0],一分钟后为[4.0,5.0,6.0],再过一分钟后变为[7.0,8.0,9.0]。假如客户端当前的时间是12点0分30秒,也就是离开始时间过去了30秒,那当前的属性值将通过在[1.0,2.0,3.0]和[4.0,5.0,6.0]线性差值得出,为[2.5,3.5,4.5]。简单起见,时间使用距离起始时间(epoch)的秒数来表示。与每个时间都通过ISO8601字符串表示相比这样不是很精确,不过对于采样间隔在一天以内,或者偏移值示整数的时候这样的精度还是绰绰有余。{//...someInterpolatableProperty:{epoch:2012-04-30T12:00Z,cartesian:[0.0,1.0,2.0,3.0,60.0,4.0,5.0,6.0,120.0,7.0,8.0,9.0]}}最后,使用时间戳采样的属性还有一些附加的可选的子属性,用来控制采样的方式。{//...someInterpolatableProperty:{epoch:2012-04-30T12:00Z,cartesian:[0.0,1.0,2.0,3.0,60.0,4.0,5.0,6.0,120.0,7.0,8.0,9.0],interpolationAlgorithm:LAGRANGE,interpolationDegree:5},}interpolationAlgorithm定义了采样使用的算法,下面的表格中列出了可能的值。interpolationDegree定义了用来插值所使用的多项式的次数,1表示线性差值,2表示二次插值法,默认为1.每个采样值的时间没有必要落在包含它的时间间隔内。但是这些采样值在他们的时间间隔内不会被使用。这样的好处就是对于多次差值有更好的精度。Itisnotnecessaryforthetimeofeverysampletofallwithintheintervalthatcontainsit,butthesampleswillnotbeusedoutsidetheirinterval.Thisisusefultoprovidebetteraccuracywithhigher-degreeinterpolation.(这句很绕啊,自己看吧)下表总结了可插值属性的一些子属性:名称Scope范围JSON类型说明epochPacketstring使用ISO8601规范来表示日期和时间nextTimePacketstringornumber在时间间隔内下一个采样的时间,可以通过ISO8061方式,也可以通过与epoch秒数来定义。它决定了不同packet之间的采样是否有停顿。previousTimePacketStringornumber在时间间隔内前一个采样的时间,可以通过ISO8061方式,也可以通过与epoch秒数来定义,它决定了不同packet之间的采样是否有停顿。InterpolationAlgorithmIntervalString用于插值的算法,有LAGTANGE,HERMITE和GEODESIC。默认是LAGRANGE。加入没有定义采样,那么这个属性值会被忽略。interpolationDegreeIntervalNumber定义了用来插值所使用的多项式的次数,1表示线性差值,2表示二次插值法,默认为1。如果使用GEODESIC插值算法,那么这个属性将被忽略。EventSourceandStreaming如果将整个CZML文件安排在一个大的JSON数组中,这使增量加载变得很困难。虽然浏览器允许我们访问没有读取完的流数据,但是解析不完整的数据需要漫长而繁琐的字符串操作。为了高效,CZML使用浏览器的server-sentevents(EventSource)API来处理流数据。在实际操作中,每一个CZML的packet包会被作为单独的一个事件传输到客户端。event:czmldata:{//packetone}event:czmldata:{//packettwo}当浏览器接收到一个packet后就会发出一个事件,事件中会包含刚刚接收到了数据。这样我们就可以