Cesium开发高级篇 | 03Property机制

Cesium中有关Property的类非常之多,算下来总共有29个,通过Property'关键词搜索结果如下图所示。对于Cesium小白或者对Cesium不太熟悉的人来说,光看搜索结果就已经很懵了,更何况是把他们熟练的用起来。



虽然关于Property类有很多,但仔细看还是有其分类的。首先Property作为基类或抽象类,定义了所有属性的接口规范,不能直接被实例化。其属性和方法如下图所示:



Property最大的特点就是和时间相互关联,它能够在不同的时间可以动态地返回不同的属性值,如空间位置。比如几何体的某一属性随时间动态变化,如高度或长度或位置等。进入Property抽象类的详细文档中,发现里面也有分类,如下图所示:

虽然官方文档没有分的特别清楚,但整体来说Cesium的Property可归结为四大类:
1)基本Property:包括ConstantProperty、SampledProperty、TimeIntervalCollectionProperty、CompositeProperty;
2)MaterialProperty:包括ColorMaterialProperty、ImageMaterialProperty、PolylineArrowMaterialProperty等;
3)PositionProperty:包括ConstantPositionProperty、SampledPositionProperty、TimeIntervalCollectionPositionProperty、CompositePositionProperty;
4)其他Property,包括CallbackProperty、NodeTransformationProperty、PropertyBag、PropertyArray、ReferenceProperty、VelocityOrientationProperty、VelocityVectorProperty。其具体分类如下图所示:


基本Property

(1)ConstantProperty
虽然我们并没有在Cesium的开发中应用到ConstantProperty,但它却是最常用的一个Property,其值不会随时间的变化而变化,Cesium内部会隐晦地将你所定义地属性(包括Property、CompositeProperty、ConstantProperty、SampledProperty、TimeIntervalCollectionProperty、MaterialProperty、PositionProperty、ReferenceProperty这几种类型)转成ConstantProperty,下面我们通过添加一个盒子地示例来说明。
默认实现代码:

 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,
          },
        });
添加ConstantProperty的方式:
        var blueBox = viewer.entities.add({
          name: "Blue box",
          position: new Cesium.ConstantProperty(Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0)),
          box: {
            dimensions: new Cesium.ConstantProperty(new Cesium.Cartesian3(400000.0, 300000.0, 500000.0)),
            material: Cesium.Color.BLUE,
          },
        });

两种实现的本质和最终的效果都是一样的。虽然ConstantProperty的值不会随时间的变化而变化,但并不代表其不可修改,我们可以通过调用setValue方法来修改其属性值。类似的还包括ConstantPositionProperty,这里就不详细介绍了,实现原理都已一样的。
(2)SampledProperty
用来通过给定多个不同时间点的Sample,然后在每两个时间点之间进行插值的一种Property,通常都会使用addSample方法添加不同时间点的值。

//Create a linearly interpolated Cartesian2
var property = new Cesium.SampledProperty(Cesium.Cartesian2);
//Populate it with data
property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:00:00.00Z'), new Cesium.Cartesian2(0, 0));
property.addSample(Cesium.JulianDate.fromIso8601('2012-08-02T00:00:00.00Z'), new Cesium.Cartesian2(4, 7));
//Retrieve an interpolated value
var result = property.getValue(Cesium.JulianDate.fromIso8601('2012-08-01T12:00:00.00Z'));

如上代码所示,最终会把property赋值给对应的属性,实现点的移动效果。
(3)TimeIntervalCollectionProperty
和SampledProperty差不多,主要区别就是SampledProperty是按照每一时刻修改Property的,实现效果是平滑的变化;而TimeIntervalCollectionProperty是按照每个时间段来修改Property的,单独每一个时间段内属性值是不变的,实现效果是跳跃式的变化。

//Create a Cartesian2 interval property which contains data on August 1st, 2012
//and uses a different value every 6 hours.
var composite = new Cesium.TimeIntervalCollectionProperty();
composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
    iso8601 : '2012-08-01T00:00:00.00Z/2012-08-01T06:00:00.00Z',
    isStartIncluded : true,
    isStopIncluded : false,
    data : new Cesium.Cartesian2(2.0, 3.4)}));
composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
    iso8601 : '2012-08-01T06:00:00.00Z/2012-08-01T12:00:00.00Z',
    isStartIncluded : true,
    isStopIncluded : false,
    data : new Cesium.Cartesian2(12.0, 2.7)}));
composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
    iso8601 : '2012-08-01T12:00:00.00Z/2012-08-01T18:00:00.00Z',
    isStartIncluded : true,
    isStopIncluded : false,
    data : new Cesium.Cartesian2(5.0, 12.4)}));
composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
    iso8601 : '2012-08-01T18:00:00.00Z/2012-08-02T00:00:00.00Z',
    isStartIncluded : true,
    isStopIncluded : true,
    data : new Cesium.Cartesian2(85.0, 4.1)}));

同样TimeIntervalCollectionPositionProperty实现原来也是类似。
(4)CompositeProperty
意思是组合的Property,有的时候单个类型的Property无法满足实际的需求时,这时可以把ConstantProperty、SampleProperty、TimeIntervalCollectionProperty等多种类型的Property组合在一起进行实现。比如一段时间线性运动,一段时间跳跃式运动,一段时间其他方式运动等,简单的示例如下:

var constantProperty = ...;
var sampledProperty = ...;
//Create a composite property from two previously defined properties
//where the property is valid on August 1st, 2012 and uses a constant
//property for the first half of the day and a sampled property for the remaining half.
var composite = new Cesium.CompositeProperty();
composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
    iso8601 : '2012-08-01T00:00:00.00Z/2012-08-01T12:00:00.00Z',
    data : constantProperty}));
composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
    iso8601 : '2012-08-01T12:00:00.00Z/2012-08-02T00:00:00.00Z',
    isStartIncluded : false,
    isStopIncluded : false,
    data : sampledProperty}));

同样还有CompositeMaterialProperty、CompositePositionProperty,是专门针对MaterialProperty、PositionProperty的CompositeProperty,其实现原理也都一样。

MaterialProperty

专门用来表示材质的Property,其中新增了获取材质类型的getType方法。和Property一样,是一个抽象类,不能直接被实例化。有关MaterialProperty的相关讲解请阅读上一篇文章Cesium开发高级篇 | 02材质设置

PositionProperty

专门用来表示Position的Property,扩展了Property的接口,增加了用于定义position坐标系原点的参考框架referenceFrame,默认值为FIXED(相当于以地球的中心作为坐标系的原点)。和Property一样,是一个抽象类,不能直接被实例化。因为PositionProperty和普通的Property本质上是一致的,用法上也大同小异,只是多了一个Position,所以对于ConstantPositionProperty、TimeIntervalCollectionPositionProperty、CompositePositionProperty不做过多的讲解,用法都在上面的基本Property中。但SampledPositionProperty在实际的开发中还比较常用,所以我们简单介绍一下它。
(1)SampledPositionProperty
SampledPositionProperty和SampledProperty原理都是一样的,简单使用方式图下:

        //Generate a random circular pattern with varying heights.
        function computeCirclularFlight(lon, lat, radius) {
          var property = new Cesium.SampledPositionProperty();
          for (var i = 0; i <= 360; i += 45) {
            var radians = Cesium.Math.toRadians(i);
            var time = Cesium.JulianDate.addSeconds(
              start,
              i,
              new Cesium.JulianDate()
            );
            var position = Cesium.Cartesian3.fromDegrees(
              lon + radius * 1.5 * Math.cos(radians),
              lat + radius * Math.sin(radians),
              Cesium.Math.nextRandomNumber() * 500 + 1750
            );
            property.addSample(time, position);

            //Also create a point for each sample we generate.
            viewer.entities.add({
              position: position,
              point: {
                pixelSize: 8,
                color: Cesium.Color.TRANSPARENT,
                outlineColor: Cesium.Color.YELLOW,
                outlineWidth: 3,
              },
            });
          }
          return property;
        }

他俩都有一个特有的方法setInterpolationOptions用于修改不同的插值方式,包括线性插值、Lagrange插值和Hermite插值,分别对应LinearApproximation、LagrangePolynomialApproximation、HermitePolynomialApproximation,详细的线性插值方式和插值效果请查看Cesium官方示例https://sandcastle.cesium.com/?src=Interpolation.html

其他Property

除了上述讲到的Property,Cesium还提供了一些其他的Property。
(1)CallbackProperty
CallbackProperty是自由度最高的一种Property,也是Cesium非常常用的一种Property,开发者可通过自定义回调函数来返回需要的值。其构造函数中包括callback和isConstant两个参数,分别表示回调函数(time和result)和回调函数每一时刻返回的值是否不变。

        var startLatitude = 35;
        var startLongitude = -120;
        var endLongitude;
        var startTime = Cesium.JulianDate.now();

        // Add a polyline to the scene. Positions are dynamic.
        var isConstant = false;
        var redLine = viewer.entities.add({
          polyline: {
            // This callback updates positions each frame.
            positions: new Cesium.CallbackProperty(function (time, result) {
              endLongitude =
                startLongitude +
                0.001 * Cesium.JulianDate.secondsDifference(time, startTime);
              return Cesium.Cartesian3.fromDegreesArray(
                [startLongitude, startLatitude, endLongitude, startLatitude],
                Cesium.Ellipsoid.WGS84,
                result
              );
            }, isConstant),
            width: 5,
            material: Cesium.Color.RED,
          },
        });

(2)PropertyBag
它的值是一个通过key-value组成的对象,其中对象中的每一个属性都是动态的,并且可以单独修改。比如只修改Box的高度,可通过如下方法实现:

    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
    });

(3)PropertyArray
和PropertyBag类似,只不过是将对象换成了数组,使用方法和PropertyBag一样,这里不再赘述。
(4)ReferenceProperty
将新Entity的属性链接到已知对象上,相当于对象属性的引用。类似于几何实例化,几何实例化是引用同一个几何对象,而ReferenceProperty是引用相同的属性,可同时控制多个Enetity的同一个属性信息,可通过如下三种方式使用。

var collection = new Cesium.EntityCollection();
//Create a new entity and assign a billboard scale.var object1 = new Cesium.Entity({id:'object1'});
object1.billboard = new Cesium.BillboardGraphics();
object1.billboard.scale = new Cesium.ConstantProperty(2.0);
collection.add(object1);

//1.Create a second entity and reference the scale from the first one.
var object2 = new Cesium.Entity({id:'object2'});
object2.model = new Cesium.ModelGraphics();
object2.model.scale = new Cesium.ReferenceProperty(collection, 'object1', ['billboard', 'scale']);
collection.add(object2);

//2.Create a third object, but use the fromString helper function.
var object3 = new Cesium.Entity({id:'object3'});
object3.billboard = new Cesium.BillboardGraphics();
object3.billboard.scale = Cesium.ReferenceProperty.fromString(collection, 'object1#billboard.scale');
collection.add(object3);

//3.You can refer to an entity with a # or . in id and property names by escaping them.
var object4 = new Cesium.Entity({id:'#object.4'});
object4.billboard = new Cesium.BillboardGraphics();
object4.billboard.scale = new Cesium.ConstantProperty(2.0);
collection.add(object4);
var object5 = new Cesium.Entity({id:'object5'});
object5.billboard = new Cesium.BillboardGraphics();
object5.billboard.scale = Cesium.ReferenceProperty.fromString(collection, '\\#object\\.4#billboard.scale');
collection.add(object5);

(5)VelocityOrientationProperty
将Entity的postion速度转换成Orientation旋转。使用方法如下:

//Create an entity with position and orientation.
var position = new Cesium.SampledProperty();
position.addSamples(...);var entity = viewer.entities.add({
  position : position,
  orientation : new Cesium.VelocityOrientationProperty(position)}));

(6)VelocityVectorProperty
和VelocityOrientationProperty类似,将速度转成Cartesian3向量。使用示例如下:

//Create an entity with a billboard rotated to match its velocity.
var position = new Cesium.SampledProperty();
position.addSamples(...);
var entity = viewer.entities.add({
  position : position,
  billboard : {
    image : 'image.png',
  alignedAxis : new Cesium.VelocityVectorProperty(position, true) // alignedAxis must be a unit vector  
}}));

(7)NodeTransformationProperty
专门用于生成 TranslationRotationScale对象的属性,包括平移、旋转、缩放,用于控制模型矩阵变化的。关于此Property,Cesium没有过多的介绍,但可以通过变相方式去使用。

        var emitterModelMatrix = new Cesium.Matrix4();
        var translation = new Cesium.Cartesian3();
        var rotation = new Cesium.Quaternion();
        var hpr = new Cesium.HeadingPitchRoll();
        var trs = new Cesium.TranslationRotationScale();

        function computeEmitterModelMatrix() {
          hpr = Cesium.HeadingPitchRoll.fromDegrees(0.0, 0.0, 0.0, hpr);
          trs.translation = Cesium.Cartesian3.fromElements(
            -4.0,
            0.0,
            1.4,
            translation
          );
          trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, rotation);

          return Cesium.Matrix4.fromTranslationRotationScale(
            trs,
            emitterModelMatrix
          );
        }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342