Cesium中文網:http://cesiumcn.org/ | 國內快速訪問:http://cesium.coinidea.com/javascript
如今咱們已經爲咱們的應用程序設置了Viewer配置、imagery和terrain的階段,咱們能夠添加咱們的應用程序的主要焦點——geocache數據。html
爲了便於可視化,Cesium支持流行的矢量格式GeoJson和KML,以及一種咱們團隊本身開源的格式,咱們專門開發用於描述Cesium場景的[]CZML](https://github.com/AnalyticalGraphicsInc/czml-writer/wiki/CZML-Guide)。java
不管初始格式如何,Cesium中的全部空間數據都使用Entity API來表示。Entity API以一種有效提供靈活的可視化的方式,以便對Cesium進行渲染。Cesium Entity是能夠與樣式化圖形表示配對並定位在空間和時間上的數據對象。測試沙盒中提供了許多簡單Entity的例子。爲了在Entity API的基礎上加快速度,從這個應用程序中休息一下,而後閱讀可視化的空間數據教程 Visualizing Spatial Data tutorial。git
如下有一些關於不一樣entity類型的例子:github
一旦你掌握了一個Entity的樣子,用Cesium裝載數據集將是變得容易理解。要讀取數據文件,須要建立適合於數據格式的數據源DataSource,該數據源將解析在指定URL中承載的數據文件,併爲數據集中的每一個地理空間對象建立包含Entity的EntityCollection。DataSource只是定義了一個接口——您須要的數據源的確切類型將取決於數據格式。例如,KML使用KmlDataSource源代碼。好比:json
var kmlOptions = { camera : viewer.scene.camera, canvas : viewer.scene.canvas, clampToGround : true }; // Load geocache points of interest from a KML file // Data from : http://catalog.opendata.city/dataset/pediacities-nyc-neighborhoods/resource/91778048-3c58-449c-a3f9-365ed203e914 var geocachePromise = Cesium.KmlDataSource.load('./Source/SampleData/sampleGeocacheLocations.kml', kmlOptions);
上述代碼讀取咱們樣例的geocahce點,從一個KML文件中,調用KmlDataSource.load(optinos)帶一些配置。針對一個KmlDataSource,相機和Canvas配置項是必須的。clamptoGround選項激活了ground clamping**,一種流行的描述配置用因而地面的幾何entities好比多邊形和橢圓符合地形並且聽從WGS84橢圓面。canvas
因爲這些數據是異步加載的,所以針對KmlDataSource返回一個的Promise,它將包含咱們全部新建立的entities。promise
若是您不熟悉使用異步函數的PromiseAPI,這裏的「異步」基本上意味着您應該在所提供的回調函數中完成所需的數據**.then.爲了實際地將這些實體集合添加到場景中,咱們必須等待直到promise完成,而後將KmlDataSource添加viewer.datasrouces**。取消如下幾行註釋:瀏覽器
// Add geocache billboard entities to scene and style them geocachePromise.then(function(dataSource) { // Add the new data as entities to the viewer viewer.dataSources.add(dataSource); });
默認狀況下,這些新建立的實體具備有用的功能。單擊將顯示與實體相關的元數據的信息框Infobox,並雙擊縮放並查看實體。若要中止查看該實體,請單擊「home」按鈕,或單擊「信息框」上的「劃出」相機圖標。接下來,咱們將添加自定義樣式來改善咱們的應用程序的外觀style。dom
對於KML和CZML文件,能夠在文件中創建聲明式樣式。然而,對於這個應用,讓咱們練習手動設計咱們的實體。要作到這一點,咱們將採起相似的方法來處理這個樣式示例,等待咱們的數據源加載,而後迭代數據源集合中的全部實體,修改和添加屬性。默認狀況下,咱們的geocache點標記被建立爲Billboards和Labels,因此爲了修改這些實體的外觀,咱們這樣作:
// Add geocache billboard entities to scene and style them geocachePromise.then(function(dataSource) { // Add the new data as entities to the viewer viewer.dataSources.add(dataSource); // Get the array of entities var geocacheEntities = dataSource.entities.values; for (var i = 0; i < geocacheEntities.length; i++) { var entity = geocacheEntities[i]; if (Cesium.defined(entity.billboard)) { // Entity styling code here } } });
咱們能夠經過調整它們的錨點、去除標籤來減小clutter和設置isplayDistanceCondition來改善標記的外觀,使得只有在距相機的必定距離內的點是可見的。
// Add geocache billboard entities to scene and style them if (Cesium.defined(entity.billboard)) { // Adjust the vertical origin so pins sit on terrain entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM; // Disable the labels to reduce clutter entity.label = undefined; // Add distance display condition entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10.0, 20000.0); }
有關distanceDisplayCondition的更多幫助,請參見sandcastle example。
接下來,讓咱們爲每一個geocache實體改進信息框Infobox。信息框的標題是實體名稱,內容是實體描述,顯示爲HTML。
你會發現默認的描述並非頗有幫助。因爲咱們正在顯示geocache 位置,讓咱們更新它們來顯示點的經度和緯度。
首先,咱們將實體的位置轉換成地圖,而後從Cartographic中讀取經度和緯度,並將其添加到HTML表中的描述中。
在單擊時,咱們的geocache 實體如今將顯示一個格式良好的信息框Infobox,只須要咱們所須要的數據。
// Add geocache billboard entities to scene and style them if (Cesium.defined(entity.billboard)) { // Adjust the vertical origin so pins sit on terrain entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM; // Disable the labels to reduce clutter entity.label = undefined; // Add distance display condition entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10.0, 20000.0); // Compute longitude and latitude in degrees var cartographicPosition = Cesium.Cartographic.fromCartesian(entity.position.getValue(Cesium.JulianDate.now())); var longitude = Cesium.Math.toDegrees(cartographicPosition.longitude); var latitude = Cesium.Math.toDegrees(cartographicPosition.latitude); // Modify description // Modify description var description = '<table class="cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>' + '<tr><th>' + "Longitude" + '</th><td>' + longitude.toFixed(5) + '</td></tr>' + '<tr><th>' + "Latitude" + '</th><td>' + latitude.toFixed(5) + '</td></tr>' + '</tbody></table>'; entity.description = description; }
咱們的geocache標記如今應該看起來像這樣:
對於咱們的地理應用程序來講,可視化特定點的鄰域也會有幫助。讓咱們試着爲每一個紐約街區記載一個包含多邊形的GeoJson文件。加載GeoJson文件最終很是相似於咱們剛剛用於KML的加載過程。可是在這種狀況下,咱們使用GeoJsonDataSource。與前一個數據源同樣,咱們須要將它添加到viewer.datasources中,以便實際添加數據到場景中。
var geojsonOptions = { clampToGround : true }; // Load neighborhood boundaries from KML file var neighborhoodsPromise = Cesium.GeoJsonDataSource.load('./Source/SampleData/neighborhoods.geojson', geojsonOptions); // Save an new entity collection of neighborhood data var neighborhoods; neighborhoodsPromise.then(function(dataSource) { // Add the new data as entities to the viewer viewer.dataSources.add(dataSource); });
讓咱們來調整咱們加載的neighborhood多邊形。就像咱們剛纔作的billboard樣式同樣,咱們首先在數據源加載後迭代遍歷neighborhood 數據源實體,此次檢查每一個實體的多邊形被定義:
// Save an new entity collection of neighborhood data var neighborhoods; neighborhoodsPromise.then(function(dataSource) { // Add the new data as entities to the viewer viewer.dataSources.add(dataSource); neighborhoods = dataSource.entities; // Get the array of entities var neighborhoodEntities = dataSource.entities.values; for (var i = 0; i < neighborhoodEntities.length; i++) { var entity = neighborhoodEntities[i]; if (Cesium.defined(entity.polygon)) { // entity styling code here } } });
既然咱們正在顯示neighborhood,讓咱們重命名每一個實體使用neighborhood做爲它的名字。咱們所讀的neighborhood中原始GeoJson文件做爲屬性。Cesium將GeoJson屬性存儲在enty.properties中,這樣咱們就能夠設置這樣的neighborhood名稱:
// entity styling code here // Use geojson neighborhood value as entity name entity.name = entity.properties.neighborhood;
咱們能夠把每個多邊形分配給一個新的顏色材料屬性,經過ColorMaterialProperty設置隨機顏色Color,而不是把全部的區域都設置成同樣的顏色。
// entity styling code here // Set the polygon material to a random, translucent color. entity.polygon.material = Cesium.Color.fromRandom({ red : 0.1, maximumGreen : 0.5, minimumBlue : 0.5, alpha : 0.6 }); // Tells the polygon to color the terrain. ClassificationType.CESIUM_3D_TILE will color the 3D tileset, and ClassificationType.BOTH will color both the 3d tiles and terrain (BOTH is the default) entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;
最後,讓咱們爲每一個實體生成一個帶有一些基本樣式選項的標籤Label。爲了保持整潔,咱們可使用disableDepthTestDistance讓Cesium老是把標籤放在任何3D物體可能遮擋的地方。
然而,請注意,標籤老是位於entity.position。多邊形Polygon是由一個未定義的位置建立的,由於它有一個定義多邊形邊界的位置列表。咱們能夠經過取多邊形位置的中心來生成一個位置:
// entity styling code here // Generate Polygon position var polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions; var polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center; polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter); entity.position = polyCenter; // Generate labels entity.label = { text : entity.name, showBackground : true, scale : 0.6, horizontalOrigin : Cesium.HorizontalOrigin.CENTER, verticalOrigin : Cesium.VerticalOrigin.BOTTOM, distanceDisplayCondition : new Cesium.DistanceDisplayCondition(10.0, 8000.0), disableDepthTestDistance : 100.0 };
這給咱們標出了看起來像這樣的多邊形:
最後,讓咱們經過在城市上空添加無人機飛行來增長咱們的NYC geocaches 的高科技視角。
因爲飛行路徑只是一系列隨時間變化的位置,因此咱們能夠從CZML文件中添加這些數據。CZML是一種用於描述時間動態圖形場景的格式,主要用於在運行Cesium的Web瀏覽器中顯示。它描述了線、點、billboards、模型和其餘圖形原語,並指定它們如何隨時間變化。CZML之於Cesium,至關於KML之於谷歌地球的標準格式,它容許大多數Cesium功能特性經過聲明式樣式語言(在這種狀況下是JSON模式)使用。
咱們的CZML文件定義了一個實體(默認爲可視化的一個點),其位置被定義爲在不一樣時間點的一系列位置。實體API中有幾種屬性類型可用於處理時間動態數據。參見下面的演示示例:
// Load a drone flight path from a CZML file var dronePromise = Cesium.CzmlDataSource.load('./Source/SampleData/SampleFlight.czml'); dronePromise.then(function(dataSource) { viewer.dataSources.add(dataSource); });
CZML文件使用Cesium來顯示無人機飛行,該路徑是實體隨時間顯示其位置的屬性。一條路徑用插值法將離散點鏈接到一條連續的直線上進行可視化。 最後,讓咱們改善無人機飛行的外觀。首先,而不是簡單地解決問題,咱們能夠加載一個3D模型來表示咱們的無人機並將其附加到實體上。
Cesium支持基於glTF(GL傳輸格式)加載3D模型,這是Cesium團隊與Khronos group一塊兒開發的開放規範,用於經過最小化文件大小和運行時間處理來有效地加載應用程序的3D模型。沒有gLTF模型嗎?咱們提供了一個在線轉換器,將COLLADA和OBJ文件轉換爲glTF格式。
讓咱們加載一個無人機模型Model,具備良好的基於物理的陰影和一些動畫:
var drone; dronePromise.then(function(dataSource) { viewer.dataSources.add(dataSource); // Get the entity using the id defined in the CZML data drone = dataSource.entities.getById('Aircraft/Aircraft1'); // Attach a 3D model drone.model = { uri : './Source/SampleData/Models/CesiumDrone.gltf', minimumPixelSize : 128, maximumScale : 1000, silhouetteColor : Cesium.Color.WHITE, silhouetteSize : 2 }; });
如今咱們的模型看起來不錯,但與原來的點不一樣,無人機模型具備方向性,當無人駕駛飛機向前移動時,它看起來很奇怪。幸運的是,Cesium提供了一種VelocityOrientationProperty,它將根據一個實體向前和向後採樣的位置自動計算方向:
// Add computed orientation based on sampled positions drone.orientation = new Cesium.VelocityOrientationProperty(drone.position);
如今咱們的無人駕駛飛機模型將如期進行。
還有一件事咱們能夠作的是改善咱們的無人機飛行的外觀。從遠處看,它可能並不明顯,但無人機的路徑是由看起來不天然的線段組成的,這是由於Cesium使用線性插值來構建從默認採樣點的路徑。然而,能夠配置插值選項。
爲了得到更平滑的飛行路徑,咱們能夠改變這樣的插值選項:
// Smooth path interpolation drone.position.setInterpolationOptions({ interpolationDegree : 3, interpolationAlgorithm : Cesium.HermitePolynomialApproximation });
Cesium中文網交流QQ羣:807482793
Cesium中文網:http://cesiumcn.org/ | 國內快速訪問:http://cesium.coinidea.com/