Cesium mechanism of Property summary

Foreword

Cesium official tutorial there is an article called "spatial data visualization" ( Visualizing the Data Spatial ). The Wenwen briefly mentioned at the end of the Cesium mechanism of Property, and then changed the subject, declared the second part of this tutorial will focus on the Property Mechanism. But then, the second part has not been written, she said that waiting for the process, you can look under the Cesium support for images and terrain. .

You can see the official tutorial statement, as shown below:

 
Cesium say the second part of the tutorial says Property of. .

So, I'm waiting for it for a year. . The second part of the tutorial official still could not see. . After all, this is one of the most important parts of Cesium official recommended the Entity API. . Actually not so long to the next update. .

I would like to summarize or your own well. .

Why Property?

Or give you an example.

For example, I think somewhere on the Earth add a box, you can write code like this:

// 创建盒子
var blueBox = viewer.entities.add({
    name : 'Blue box',
    position: Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0), box : { dimensions : new Cesium.Cartesian3(400000.0, 300000.0, 500000.0), material : Cesium.Color.BLUE, outline: true, } }); 

The final results as shown:

 
box in a fixed position plus

But then, if I want this box begin to get longer, how does it work? As shown below:

 
Box progressively longer

The method is there, is that you can keep to modify blueBox.position, like this:
setInterval(function(){ blueBox.box.dimensions = xxx; }, 3000);

If there are many objects in the scene, while a variety of different time periods stop and go movement to occur, this operation may tiring. So Cesium provides a mechanism so that dimensions can occur automatically change over time, automatically assigned different values ​​(position). This is the role of the property. The following code is added, so that the box can be made as shown above the linear motion.

    var property = new Cesium.SampledProperty(Cesium.Cartesian3);

    property.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 
        new Cesium.Cartesian3(400000.0, 300000.0, 200000.0)); property.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'), new Cesium.Cartesian3(400000.0, 300000.0, 700000.0)); blueBox.box.dimensions = property; 

Code above means that at two different points in time are given a different position, with SampledProperty packed into a Property, the last assigned blueBox.box.dimensions.

由此可见,Property最大的特点是和时间相互关联,在不同的时间可以动态地返回不同的属性值。而Entity则可以感知这些Property的变化,在不同的时间驱动物体进行动态展示。

Cesium宣称自己是数据驱动和time-dynamic visualization,这些可都是仰仗Property系统来实现的。

当然,Property可不只是这么简单,以下再详细论述。

Property的分类

Cesium的Property不止有刚才示例代码中的SampleProperty,还有很多其他的类型。如果搜索一下Cesium的API文档,会有很多。。如下图所示:

 
Cesium API文档搜索Property

我们简单分类一下

 
image.png

Property虚基类

Property是所有Property类型的虚基类。它定义了以下接口。

 
Property类型的公共接口

getValue 是一个方法,用来获取某个时间点的特定属性值。它有两个参数:第一个是time,用来传递一个时间点;第二个是result,用来存储属性值,当然也可以是undefined。这个result是Cesium的scratch机制,主要是用来避免频繁创建和销毁对象而导致内存碎片。Cesium就是通过调用getValue类似的一些函数来感知Property的变化的,当然这个方法我们在外部也是可以使用的。

isConstant 用来判断该属性是否会随时间变化,是一个布尔值。Cesium会通过这个变量来决定是否需要在场景更新的每一帧中都获取该属性的数值,从而来更新三维场景中的物体。如果isConstant为true,则只会获取一次数值,除非definitionChanged事件被触发。

definitionChanged 是一个事件,可以通过该事件,来监听该Property自身所发生的变化,比如数值发生修改。

equals 是一个方法,用来检测属性值是否相等。

基本Property类型

SampleProperty

我们最早在上述示例中使用的就是它,用来通过给定多个不同时间点的Sample,然后在每两个时间点之间进行线性插值的一种Property。代码写法如下:

    var property = new Cesium.SampledProperty(Cesium.Cartesian3);

    property.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 
        new Cesium.Cartesian3(400000.0, 300000.0, 200000.0)); property.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'), new Cesium.Cartesian3(400000.0, 300000.0, 700000.0)); blueBox.box.dimensions = property; 

效果如下所示:

 
盒子逐渐变长

TimeIntervalCollectionProperty

该Property用来指定各个具体的时间段的属性值,每个时间段内的属性值是恒定的,并不会发生变化,除非已经进入到下一个时间段。拿创建的盒子示例来说,表现出来的特点就是盒子尺寸的变化时跳跃式的。效果如下:

 
2.gif

代码如下:

    var property = new Cesium.TimeIntervalCollectionProperty(Cesium.Cartesian3);

    property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
        iso8601 : '2019-01-01T00:00:00.00Z/2019-01-01T12:00:00.00Z',
        isStartIncluded : true, isStopIncluded : false, data : new Cesium.Cartesian3(400000.0, 300000.0, 200000.0) })); property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({ iso8601 : '2019-01-01T12:00:01.00Z/2019-01-02T00:00:00.00Z', isStartIncluded : true, isStopIncluded : false, data : new Cesium.Cartesian3(400000.0, 300000.0, 400000.0) })); property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({ iso8601 : '2019-01-02T00:00:01.00Z/2019-01-02T12:00:00.00Z', isStartIncluded : true, isStopIncluded : false, data : new Cesium.Cartesian3(400000.0, 300000.0, 500000.0) })); property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({ iso8601 : '2019-01-02T12:00:01.00Z/2019-01-03T00:00:00.00Z', isStartIncluded : true, isStopIncluded : true, data : new Cesium.Cartesian3(400000.0, 300000.0, 700000.0) })); blueBox.box.dimensions = property; 

ConstantProperty

通过对TimeIntervalCollectionProperty和SampleProperty的描述,读者应该基本了解Property的特点。我们回过头来说下ConstantProperty,其实这才是最常用的Property。

示例代码如下:

blueBox.box.dimensions = new Cesium.Cartesian3(400000.0, 300000.0, 200000.0);

以上代码貌似没有使用ConstantProperty,实际上他是等同于:

blueBox.box.dimensions = new ConstantProperty(new Cesium.Cartesian3(400000.0, 300000.0, 200000.0)); 

也就是Entity的box.dimensions类型并不是Cartesian3,而是一个Property。虽然我们赋值了一个Cartesian3,但是Cesium内部会隐晦地转化成了一个ConstantProperty。注意只会隐晦地转化成ConstantProperty,而不是SampleProperty,更不是TimeIntervalCollectionProperty。

虽然叫ConstantProperty,但是,这里Constant的意思并不是说这个Property不可改变,而是说它不会随时间发生变化。

举个例子,我们可以通过 property.getValue(viewer.clock.currentTime) 方法来获取某个时间点property的属性值。如果property是SampleProperty或者TimeIntervalCollectionProperty的话,不同的时间点,可能getValue出不同的数值。但是如果这个property是ConstantProperty,那么无论什么时间(getValue的第一个参数不起作用),最后返回的数值都是一样的。

但是不会随时间变化,并不代表不可改变。ConstantProperty还有一个setValue的方法,开发者可以通过调用它,来在适当的时候改变property的值。

比如,我可以通过点击按钮来修改ConstantProperty,代码如下:

blueBox.box.dimensions.setValue(new Cesium.Cartesian3(400000.0, 300000.0, 700000.0)); 

需要注意的是,虽然最终效果一样,但是以下两种写法的意义是不一样的。

blueBox.box.dimensions = new Cesium.Cartesian3(400000.0, 300000.0, 200000.0);

blueBox.box.dimensions.setValue(new Cesium.Cartesian3(400000.0, 300000.0, 700000.0));

前者会创建一个新的ConstantProperty,后者则会修改原有的ConstantProperty的值。

CompositeProperty

CompositeProperty的意思是组合的Property,可以把多种不同类型的ConstantProperty、SampleProperty、TimeIntervalCollectionProperty等Property组合在一起来操作。比如前一个时间段需要线性运动,后一段时间再跳跃式运动。则可以使用类似下面这段代码来实现。

    // 1 sampledProperty
    var sampledProperty = new Cesium.SampledProperty(Cesium.Cartesian3);
    sampledProperty.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 
        new Cesium.Cartesian3(400000.0, 300000.0, 200000.0)); sampledProperty.addSample(Cesium.JulianDate.fromIso8601('2019-01-02T00:00:00.00Z'), new Cesium.Cartesian3(400000.0, 300000.0, 400000.0)); // 2 ticProperty var ticProperty = new Cesium.TimeIntervalCollectionProperty(); ticProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({ iso8601 : '2019-01-02T00:00:00.00Z/2019-01-02T06:00:00.00Z', isStartIncluded : true, isStopIncluded : false, data : new Cesium.Cartesian3(400000.0, 300000.0, 400000.0) })); ticProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({ iso8601 : '2019-01-02T06:00:00.00Z/2019-01-02T12:00:00.00Z', isStartIncluded : true, isStopIncluded : false, data : new Cesium.Cartesian3(400000.0, 300000.0, 500000.0) })); ticProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({ iso8601 : '2019-01-02T12:00:00.00Z/2019-01-02T18:00:00.00Z', isStartIncluded : true, isStopIncluded : false, data : new Cesium.Cartesian3(400000.0, 300000.0, 600000.0) })); ticProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({ iso8601 : '2019-01-02T18:00:00.00Z/2019-01-03T23:00:00.00Z', isStartIncluded : true, isStopIncluded : true, data : new Cesium.Cartesian3(400000.0, 300000.0, 700000.0) })); // 3 compositeProperty var compositeProperty = new Cesium.CompositeProperty(); compositeProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({ iso8601 : '2019-01-01T00:00:00.00Z/2019-01-02T00:00:00.00Z', data : sampledProperty })); compositeProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({ iso8601 : '2019-01-02T00:00:00.00Z/2019-01-03T00:00:00.00Z', isStartIncluded : false, isStopIncluded : false, data : ticProperty })); // 4 设置position blueBox.box.dimensions = compositeProperty; 

最终实现的效果如下:

 
CompositeProperty

PositionProperty

以上示例可以看到,我们一直在用SampledProperty、ConstantProperty等来修改Entity的box.dimensions属性。基本上可以得出结论:大部分Property都是可以赋值给Entity的box.dimensions的。

PositionProperty和Property一样,是一个虚类,并不能直接实例化,他扩展了Property的接口,增加了referenceFrame,同时只能用来表示position。

 
PositionProperty

referenceFrame是用来表示position的参考架。目前Cesium有以下两种参考架。

 
image.png

我们常用的是FIXED这种默认类型,它相当于以地球的中心作为坐标系的原点,x轴正向指向赤道和本初子午线的交点。(可能描述不准确。。)这样我们给定一个笛卡尔坐标(x, y, z),它在地球上的位置是固定的。

而INERTIAL这种类型,则相当于以太阳系的质心为原点的坐标架偏移到地球的中心来,如果给定一个笛卡尔坐标(x, y, z),那么它在不同的时间表示的是地球上的不同位置。。(我的理解,可能有误。。)

一般情况下,我们用不上INERTIAL。但是如果真的给定了INERTIAL下的坐标点,Cesium内部会通过PositionProperty,把它转成同一个FIXED下的坐标点来使用,这些不需要我们操作。

但是,因为普通的Property是没有办法进行这种参考架的自动转换的,所以Cesium派生了一批PositionProperty类型。

基于PositionProperty的类型有以下几种:
CompositePositionProperty
ConstantPositionProperty
PositionProperty
PositionPropertyArray
SampledPositionProperty
TimeIntervalCollectionPositionProperty

稍加留意,就会发现,和普通的Property相比,只是多了一个Position,所以用法上也大同小异,只不过他们是用来专门表示位置的。

SampledPositionProperty

SampledPositionProperty的用法,不多解释,直接看代码吧:

    var property = new Cesium.SampledPositionProperty();

    property.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 
        Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0)); property.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'), Cesium.Cartesian3.fromDegrees(-114.0, 45.0, 300000.0)); blueBox.position = property; 

效果如下:

 
SampledPositionProperty

SampleProperty和SampledPositionProperty有一个特有的方法:setInterpolationOptions,用来修改不同的插值方式。以下是以Cesium的Interpolation示例中的截图来说明他们的不同之处。

线性插值
 
线性插值

代码写法如下:

entity.position.setInterpolationOptions({
    interpolationDegree : 1, interpolationAlgorithm : Cesium.LinearApproximation }); 
Lagrange插值
 
Lagrange插值
entity.position.setInterpolationOptions({
    interpolationDegree : 5, interpolationAlgorithm : Cesium.LagrangePolynomialApproximation }); 
Hermite插值
 
Hermite插值
entity.position.setInterpolationOptions({
    interpolationDegree : 2, interpolationAlgorithm : Cesium.HermitePolynomialApproximation }); 

MaterialProperty

MaterialProperty是用来专门表示材质的Property,它对Property进行了扩展,增加了getType方法,用来获取材质类型。

 
image.png

MaterialProperty也是一个虚基类,派生类有:
CheckerboardMaterialProperty
ColorMaterialProperty
CompositeMaterialProperty
GridMaterialProperty
ImageMaterialProperty
MaterialProperty
PolylineArrowMaterialProperty
PolylineDashMaterialProperty
PolylineGlowMaterialProperty
PolylineOutlineMaterialProperty
StripeMaterialProperty

使用上大同小异,我们以ColorMaterialProperty来说明一下。

ColorMaterialProperty

    blueBox.box.material = new Cesium.ColorMaterialProperty(new Cesium.Color(0, 1, 0)); // 以上代码等同于 // blueBox.box.material = new Cesium.Color(0, 1, 0); 

效果如下:

 
ColorMaterialProperty

ColorMaterialProperty的动态变化

如果希望Color动起来的话,也是可以的。ColorMaterialProperty的内部有一个color属性,可以赋予一个SampledProperty来实现动态效果。

    var colorProperty = new Cesium.SampledProperty(Cesium.Color);

    colorProperty.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 
        new Cesium.Color(0, 1, 0)); colorProperty.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'), new Cesium.Color(0, 0, 1)); blueBox.box.material = new Cesium.ColorMaterialProperty(colorProperty); 

效果如下:

 
ColorMaterialProperty的动态变化

其他类型的Property

CallbackProperty

CallbackProperty是自由度最高的一种Property,让用户通过自定义,回调函数,来返回需要的值。回调函数中,用户可以使用time来给定value,也可以以自己的方式给给定。

以下代码就是不通过time,自己手动调整dimension的示例。

    var l = 200000.0;
    var property = new Cesium.CallbackProperty(function (time, result) { result = result || new Cesium.Cartesian3(0, 0, 0); l += 10000.0; if (l > 700000.0) { l = 200000.0; } result.x = 400000.0; result.y = 300000.0; result.z = l; return result; }, false); blueBox.box.dimensions = property; 

效果如下:

 
盒子逐渐变长

ReferenceProperty

该Property可以直接链接到别的对象的Property上,相当于引用,省得自己构建了。比如这里我创建了一个红色的盒子redBox,希望它和之前的蓝色盒子一起变大。那么可以使用以下代码:

    var collection = viewer.entities;
    redBox.box.dimensions = new Cesium.ReferenceProperty(collection, blueBox.id, ['box', 'dimensions']);

效果如下:

 
ReferenceProperty的使用
 
ReferenceProperty构造函数的参数

ReferenceProperty构造函数的参数有三个。第一个参数用来指定需要引用的对象所属的collection,如果没有自己专门创建EntityCollection的话,可以直接使用viewer.entities。第二个参数传递所指对象的id。第三个参数指定属性的位置的数组,如果是有层级的属性,可以依次写入。比如 ['billboard', 'scale'] 指定的是entity.billboard.scale 属性。当然还有其他设置方式,可以参见Cesium的api文档。

PropertyBag

PropertyBag虽然不是以Property结尾,但实际上也是一个Property。它的特点是可以包装一个对象(JS中的对象概念),该对象的每一个属性(JS中的属性概念),都可以作为一个动态的Property。

比如之前修改dimensions的话,dimensions是作为一个Cartesian3类型变量整体封装到Property中去的,如果我们只想修改dimensions的x。则可以使用PropertyBag来实现,代码如下:

    var zp = new Cesium.SampledProperty(Number);
    zp.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 200000.0); zp.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'), 700000.0); blueBox.box.dimensions = new Cesium.PropertyBag({ x: 400000.0, y: 300000.0, z: zp }); 
 
PropertyBag的使用

效果和sampleProperty类似,但是修改的只是dimensions的x。

PropertyArray

PropertyArray和上述的PropertyBag类似,只是其内部封装了一个数组而已。这里不再赘述。

VelocityOrientationProperty

该Property用来Entity的position的位置变化,来计算出移动的方向,最后把速度方向输出成Orientation。Cesium自带的示例中有一个Interpolation中有其用法,不再赘述。

VelocityVectorProperty

与上面的Property类似,把速度方向转成Vector。使用示例如下:

    blueBox.box.show = false;
    blueBox.billboard = {
        scale: 0.05,
        image : 'https://upload-images.jianshu.io/upload_images/80648-5dfe8a3ea2c250be.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/540/format/webp',
        alignedAxis : new Cesium.VelocityVectorProperty(blueBox.position, true) // alignedAxis must be a unit vector }; 

可见图像的摆放方向和位置移动的方向保持一致。效果如下:

 
VelocityVectorProperty

附录

本文在github上的源码



作者:vtxf
链接:https://www.jianshu.com/p/f0b47997224c
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

Guess you like

Origin www.cnblogs.com/telwanggs/p/11290024.html