Cesium的Property機制總結[轉]

https://www.jianshu.com/p/f0b47997224c

前言

Cesium官方教程中有一篇叫《空間數據可視化》(Visualizing Spatial Data)。該文文末簡單提到了Cesium的Property機制,而後話鋒一轉,宣告此教程的第二部分將重點講解Property機制。可是呢,第二部分尚未寫好,說在等待的過程當中,能夠先看下Cesium對影像和地形的支持。。css

能夠看官方教程中的說法,以下圖所示:web

 
Cesium說教程的第二部分說Property的。。

因而,我苦等了一年啦。。官方教程的第二部分仍是沒能看到。。畢竟這是Cesium官方推薦使用的Entity API中最重要的部分之一。。竟然這麼久了也不給更新下。。api

我想仍是本身總結一下得好。。數組

爲何要用Property?

仍是舉個例子來講吧。函數

好比我想在地球上的某個位置加一個盒子,能夠這樣寫代碼:spa

// 建立盒子 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, } }); 

最終的效果如圖所示:3d

 
box加在固定位置

可是呢,若是我想讓這個盒子逐漸變長,該怎麼操做呢?以下圖所示:code

 
盒子逐漸變長

方法是有的,就是能夠不停地去修改blueBox.position,相似這樣:
setInterval(function(){ blueBox.box.dimensions = xxx; }, 3000);orm

若是場景中有不少物體,在不一樣的時間段要發生各類走走停停地運動時,這樣操做可能會很累人。那麼Cesium就提供一種機制,讓dimensions能夠隨時間自動發生變化,自動賦予不一樣的數值(位置)。這也就是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; 

以上代碼的意思就是在兩個不一樣的時間點分別賦予不一樣的位置,用SampledProperty包裝成一個property,最後賦給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
做者:vtxf 連接:https://www.jianshu.com/p/f0b47997224c 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索