Cesium实现三维可视化一般步骤
在项目的开发过程中用到在底图显示三维可视化图形,涉及到加载大批量的数据,经过查阅资料,决定采用Cesium设计一个实现方案,在底图显示3d模型以及与3d模型之间的一系列交互行为,下面分步骤详细进行介绍:
- 创建查看器—将查看器添加到指定的铯容器cesiumContainer,可以实现底图的切换,加载天地图。代码如下所示:
var viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider : new Cesium.createOpenStreetMapImageryProvider({
url : 'https://a.tile.openstreetmap.org/'
}),
baseLayerPicker : false,
animation : false,
timeline : false,
fullscreenButton : false,
infoBox : false,
homeButton : false
});
2.相机控制—由属性viewer.scene控制当前可见的内容,可以通过设置相机的位置和方向来控制相机切换视角,也可以使用cesium相机API来设置相机的位置和方向。
//Create an initial camera view
var initialPosition = new Cesium.Cartesian3.fromDegrees(-73.848114468289017509, 40.824512895646692812, 2631.082799425431);
var initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(7.1077496389876024807, -31.987223091598949054, 0.025883251314954971306);
var homeCameraView = {
destination : initialPosition,
orientation : {
heading : initialOrientation.heading,//围绕负z轴的旋转
pitch : initialOrientation.pitch,//围绕负y轴的旋转
roll : initialOrientation.roll//围绕正x轴的旋转
}
};
viewer.scene.camera.setView(homeCameraView); //将相机设定在特定的位置和方向
3.加载样式实体—为了便于观看,cesium支持流行的矢量格式GeoJson和KML,以及我们专门为描述cesium中称为CZML的场景而开发的开放格式。其中DataSource只是定义了一个接口,需要的确切类型的数据源将取决于数据格式。
(1) KML使用KmlDataSource,通过调用KmlDataSource.load(optinos)几个选项从KML文件中读取我们的示例geocache点。对于KmlDataSource,需要相机和画布选项。该clampToGround选项支持地面夹紧,这是一种流行的显示选项,可使地形几何实体(如多边形和椭圆)符合地形而不是曲线到WGS84椭球表面。
var kmlOptions = {
camera : viewer.scene.camera,//相机选项
canvas : viewer.scene.canvas,//画布选项
clampToGround : true
};
// Load geocache points of interest from a KML file
var geocachePromise = Cesium.KmlDataSource.load('./SampleData/kml/bikeRide.kml', kmlOptions);
// 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)) {
// 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 latitude and longitude in degrees
var cartographicPosition = Cesium.Cartographic.fromCartesian(entity.position.getValue(Cesium.JulianDate.now()));
var latitude = Cesium.Math.toDegrees(cartographicPosition.latitude);
var longitude = Cesium.Math.toDegrees(cartographicPosition.longitude);
// Modify description
var description = '<table class="cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>';
description += '<tr><th>' + "Latitude" + '</th><td>' + latitude + '</td></tr>';
description += '<tr><th>' + "Longitude" + '</th><td>' + longitude + '</td></tr>';
description += '</tbody></table>';
entity.description = description;
}
}
});
(2) GeoJson与加载KML的过程非常相似,在这种情况下,可以使用GeoJsonDataSource代替,和前面的数据源一样,需要将viewer.dataSources添加数据到场景中。这种加载方式只是实现的平面的,可以通过自行设置高度entity.polygon.extrudedHeight读取每个实体属性中的高度
使建筑物看起来有一定的高度,切换视角,达到三维效果;加载geojson文件添加鼠标交互行为不生效;使用这种方式加载大批量的建筑物会造成浏览器卡顿甚至崩溃。
var geojsonOptions = {
clampToGround : true
};
// Load neighborhood boundaries from KML file
var neighborhoodsPromise = Cesium.GeoJsonDataSource.load('./SampleData/test.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
var city = 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
entity.name = entity.properties.neighborhood;
// entity.polygon.material = Cesium.Color.fromRandom({
// red : 0.4,
// maximumGreen :0.8,
// minimumBlue : 0.6,
// alpha :1
// });
entity.polygon.material = Cesium.Color.YELLOW;
entity.polygon.outline = false;
// 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;
// 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;
entity.polygon.extrudedHeight = entity.properties.height;
// entity.polygon.height = entity.properties.height;
// 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
};
}
}
//加载的建筑物的总数
console.log(neighborhoodEntities.length);
});
(3) Cesium支持基于glTF(GL传输格式)加载3D模型,加载模型与迄今为止我们使用过的任何其他类型的可视化没有什么不同,所需要的只是实体的位置和glTF模型的一个URL;每个模型都有自己的原始COLLADA文件(.dae)和glTF文件(.gltf),在Cesium中我们不需要原始的COLLADA文件,需要的只是经过3d
max转化后的gltf文件以及相应的贴图文件。(例子中定位到宾夕法尼亚州埃克斯顿就是通过加载.gltf格式的数据渲染到地图上)。
var scene = viewer.scene;
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(-75.62898254394531, 40.02804946899414, 0.0));
var model = scene.primitives.add(Cesium.Model.fromGltf({
url : './SampleData/models/CesiumGround/Cesium_Ground.gltf',
modelMatrix : modelMatrix,
scale : 200.0
}));
4、 鼠标交互—只有在加载3d Tiles的时候,才可以用鼠标实现交互选择和样式改变,否则这些模型将无法以交互方式查看。在这种情况下可以加载大批量的模型建筑物信息。例如viewer.scene.primitives.add(new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(3839) }));显示纽约所有的建筑物完整的3d模型,从而为三维可视化添加真实感。
说明:如果要加载大批量的模型,以dataSource加载geojson文件的方法可能会造成浏览器卡顿甚至崩溃的现象;3d Tiles才是实现加载大规模场景应用的最佳选择,而且依赖于3d Tiles还可以实现鼠标交互改变样式等。