Cesium入門9 - Loading and Styling Entities - 加載和樣式化實(shí)體

Cesium入門9 - Loading and Styling Entities - 加載和樣式化實(shí)體

Cesium中文網(wǎng):http://cesiumcn.org/ | 國內(nèi)快速訪問:http://cesium.coinidea.com/

現(xiàn)在我們已經(jīng)為我們的應(yīng)用程序設(shè)置了Viewer配置、imagery和terrain的階段,我們可以添加我們的應(yīng)用程序的主要焦點(diǎn)——geocache數(shù)據(jù)。

為了便于可視化,Cesium支持流行的矢量格式GeoJson和KML,以及一種我們團(tuán)隊(duì)自己開源的格式,我們專門開發(fā)用于描述Cesium場(chǎng)景的[]CZML](https://github.com/AnalyticalGraphicsInc/czml-writer/wiki/CZML-Guide)。

無論初始格式如何,Cesium中的所有空間數(shù)據(jù)都使用Entity API來表示。Entity API以一種有效提供靈活的可視化的方式,以便對(duì)Cesium進(jìn)行渲染。Cesium Entity是可以與樣式化圖形表示配對(duì)并定位在空間和時(shí)間上的數(shù)據(jù)對(duì)象。測(cè)試沙盒中提供了許多簡(jiǎn)單Entity的例子。為了在Entity API的基礎(chǔ)上加快速度,從這個(gè)應(yīng)用程序中休息一下,然后閱讀可視化的空間數(shù)據(jù)教程 Visualizing Spatial Data tutorial

以下有一些關(guān)于不同entity類型的例子:

一旦你掌握了一個(gè)Entity的樣子,用Cesium裝載數(shù)據(jù)集將是變得容易理解。要讀取數(shù)據(jù)文件,需要?jiǎng)?chuàng)建適合于數(shù)據(jù)格式的數(shù)據(jù)源DataSource,該數(shù)據(jù)源將解析在指定URL中承載的數(shù)據(jù)文件,并為數(shù)據(jù)集中的每個(gè)地理空間對(duì)象創(chuàng)建包含EntityEntityCollection。DataSource只是定義了一個(gè)接口——您需要的數(shù)據(jù)源的確切類型將取決于數(shù)據(jù)格式。例如,KML使用KmlDataSource源代碼。比如:

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點(diǎn),從一個(gè)KML文件中,調(diào)用KmlDataSource.load(optinos)帶一些配置。針對(duì)一個(gè)KmlDataSource,相機(jī)和Canvas配置項(xiàng)是必須的。clamptoGround選項(xiàng)激活了ground clamping,一種流行的描述配置用于是地面的幾何entities比如多邊形和橢圓符合地形而且遵從WGS84橢圓面。

由于這些數(shù)據(jù)是異步加載的,因此針對(duì)KmlDataSource返回一個(gè)的Promise,它將包含我們所有新創(chuàng)建的entities。

如果您不熟悉使用異步函數(shù)的PromiseAPI,這里的“異步”基本上意味著您應(yīng)該在所提供的回調(diào)函數(shù)中完成所需的數(shù)據(jù).then.為了實(shí)際地將這些實(shí)體集合添加到場(chǎng)景中,我們必須等待直到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);
});

默認(rèn)情況下,這些新創(chuàng)建的實(shí)體具有有用的功能。單擊將顯示與實(shí)體相關(guān)的元數(shù)據(jù)的信息框Infobox,并雙擊縮放并查看實(shí)體。若要停止查看該實(shí)體,請(qǐng)單擊“home”按鈕,或單擊“信息框”上的“劃出”相機(jī)圖標(biāo)。接下來,我們將添加自定義樣式來改善我們的應(yīng)用程序的外觀style。

對(duì)于KML和CZML文件,可以在文件中建立聲明式樣式。然而,對(duì)于這個(gè)應(yīng)用,讓我們練習(xí)手動(dòng)設(shè)計(jì)我們的實(shí)體。要做到這一點(diǎn),我們將采取類似的方法來處理這個(gè)樣式示例,等待我們的數(shù)據(jù)源加載,然后迭代數(shù)據(jù)源集合中的所有實(shí)體,修改和添加屬性。默認(rèn)情況下,我們的geocache點(diǎn)標(biāo)記被創(chuàng)建為BillboardsLabels,所以為了修改這些實(shí)體的外觀,我們這樣做:

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

我們可以通過調(diào)整它們的錨點(diǎn)、去除標(biāo)簽來減少clutter和設(shè)置isplayDistanceCondition來改善標(biāo)記的外觀,使得只有在距相機(jī)的一定距離內(nèi)的點(diǎn)是可見的。

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

有關(guān)distanceDisplayCondition的更多幫助,請(qǐng)參見sandcastle example。

接下來,讓我們?yōu)槊總€(gè)geocache實(shí)體改進(jìn)信息框Infobox。信息框的標(biāo)題是實(shí)體名稱,內(nèi)容是實(shí)體描述,顯示為HTML。

你會(huì)發(fā)現(xiàn)默認(rèn)的描述并不是很有幫助。由于我們正在顯示geocache 位置,讓我們更新它們來顯示點(diǎn)的經(jīng)度和緯度。

首先,我們將實(shí)體的位置轉(zhuǎn)換成地圖,然后從Cartographic中讀取經(jīng)度和緯度,并將其添加到HTML表中的描述中。

在單擊時(shí),我們的geocache 實(shí)體現(xiàn)在將顯示一個(gè)格式良好的信息框Infobox,只需要我們所需要的數(shù)據(jù)。

// 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標(biāo)記現(xiàn)在應(yīng)該看起來像這樣:


image

對(duì)于我們的地理應(yīng)用程序來說,可視化特定點(diǎn)的鄰域也會(huì)有幫助。讓我們?cè)囍鵀槊總€(gè)紐約街區(qū)記載一個(gè)包含多邊形的GeoJson文件。加載GeoJson文件最終非常類似于我們剛剛用于KML的加載過程。但是在這種情況下,我們使用GeoJsonDataSource。與前一個(gè)數(shù)據(jù)源一樣,我們需要將它添加到viewer.datasources中,以便實(shí)際添加數(shù)據(jù)到場(chǎng)景中。

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

讓我們來調(diào)整我們加載的neighborhood多邊形。就像我們剛才做的billboard樣式一樣,我們首先在數(shù)據(jù)源加載后迭代遍歷neighborhood 數(shù)據(jù)源實(shí)體,這次檢查每個(gè)實(shí)體的多邊形被定義:

// 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,讓我們重命名每個(gè)實(shí)體使用neighborhood作為它的名字。我們所讀的neighborhood中原始GeoJson文件作為屬性。Cesium將GeoJson屬性存儲(chǔ)在enty.properties中,這樣我們就可以設(shè)置這樣的neighborhood名稱:

// entity styling code here

// Use geojson neighborhood value as entity name
entity.name = entity.properties.neighborhood;

我們可以把每一個(gè)多邊形分配給一個(gè)新的顏色材料屬性,通過ColorMaterialProperty設(shè)置隨機(jī)顏色Color,而不是把所有的區(qū)域都設(shè)置成一樣的顏色。

// 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;

最后,讓我們?yōu)槊總€(gè)實(shí)體生成一個(gè)帶有一些基本樣式選項(xiàng)的標(biāo)簽Label。為了保持整潔,我們可以使用disableDepthTestDistance讓Cesium總是把標(biāo)簽放在任何3D物體可能遮擋的地方。

然而,請(qǐng)注意,標(biāo)簽總是位于entity.position。多邊形Polygon是由一個(gè)未定義的位置創(chuàng)建的,因?yàn)樗幸粋€(gè)定義多邊形邊界的位置列表。我們可以通過取多邊形位置的中心來生成一個(gè)位置:

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

這給我們標(biāo)出了看起來像這樣的多邊形:


image

最后,讓我們通過在城市上空添加無人機(jī)飛行來增加我們的NYC geocaches 的高科技視角。

由于飛行路徑只是一系列隨時(shí)間變化的位置,所以我們可以從CZML文件中添加這些數(shù)據(jù)。CZML是一種用于描述時(shí)間動(dòng)態(tài)圖形場(chǎng)景的格式,主要用于在運(yùn)行Cesium的Web瀏覽器中顯示。它描述了線、點(diǎn)、billboards、模型和其他圖形原語,并指定它們?nèi)绾坞S時(shí)間變化。CZML之于Cesium,相當(dāng)于KML之于谷歌地球的標(biāo)準(zhǔn)格式,它允許大多數(shù)Cesium功能特性通過聲明式樣式語言(在這種情況下是JSON模式)使用。

我們的CZML文件定義了一個(gè)實(shí)體(默認(rèn)為可視化的一個(gè)點(diǎn)),其位置被定義為在不同時(shí)間點(diǎn)的一系列位置。實(shí)體API中有幾種屬性類型可用于處理時(shí)間動(dòng)態(tài)數(shù)據(jù)。參見下面的演示示例:

// 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來顯示無人機(jī)飛行,該路徑是實(shí)體隨時(shí)間顯示其位置的屬性。一條路徑用插值法將離散點(diǎn)連接到一條連續(xù)的直線上進(jìn)行可視化。
最后,讓我們改善無人機(jī)飛行的外觀。首先,而不是簡(jiǎn)單地解決問題,我們可以加載一個(gè)3D模型來表示我們的無人機(jī)并將其附加到實(shí)體上。

Cesium支持基于glTF(GL傳輸格式)加載3D模型,這是Cesium團(tuán)隊(duì)與Khronos group一起開發(fā)的開放規(guī)范,用于通過最小化文件大小和運(yùn)行時(shí)間處理來有效地加載應(yīng)用程序的3D模型。沒有g(shù)LTF模型嗎?我們提供了一個(gè)在線轉(zhuǎn)換器,將COLLADA和OBJ文件轉(zhuǎn)換為glTF格式。

讓我們加載一個(gè)無人機(jī)模型Model,具有良好的基于物理的陰影和一些動(dòng)畫:

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

現(xiàn)在我們的模型看起來不錯(cuò),但與原來的點(diǎn)不同,無人機(jī)模型具有方向性,當(dāng)無人駕駛飛機(jī)向前移動(dòng)時(shí),它看起來很奇怪。幸運(yùn)的是,Cesium提供了一種VelocityOrientationProperty,它將根據(jù)一個(gè)實(shí)體向前和向后采樣的位置自動(dòng)計(jì)算方向:

// Add computed orientation based on sampled positions
drone.orientation = new Cesium.VelocityOrientationProperty(drone.position);

現(xiàn)在我們的無人駕駛飛機(jī)模型將如期進(jìn)行。

還有一件事我們可以做的是改善我們的無人機(jī)飛行的外觀。從遠(yuǎn)處看,它可能并不明顯,但無人機(jī)的路徑是由看起來不自然的線段組成的,這是因?yàn)镃esium使用線性插值來構(gòu)建從默認(rèn)采樣點(diǎn)的路徑。然而,可以配置插值選項(xiàng)。

為了獲得更平滑的飛行路徑,我們可以改變這樣的插值選項(xiàng):

// Smooth path interpolation
drone.position.setInterpolationOptions({
    interpolationDegree : 3,
    interpolationAlgorithm : Cesium.HermitePolynomialApproximation
});
image

Cesium中文網(wǎng):http://cesiumcn.org/ | 國內(nèi)快速訪問:http://cesium.coinidea.com/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容