第一次接触Cesium的图形标注功能时,我完全被它强大的可视化能力震撼到了。作为一个地理信息系统开发者,我经常需要在三维地球上标注各种区域和建筑,而Cesium提供的几何图形API让这一切变得异常简单。
Cesium的图形标注主要分为两大类:平面图形和立体图形。平面图形包括我们常见的圆形、矩形、多边形等,而立体图形则是在此基础上增加了高度信息,可以构建出立方体、圆柱体等三维模型。在实际项目中,这两种图形经常需要配合使用,比如在地图上标注一个建筑区域(平面多边形)的同时,还需要用立体柱体表示建筑高度。
先来看个最简单的例子 - 绘制一个矩形。在Cesium中,矩形是通过指定四个角的经纬度来定义的:
javascript复制const rectangle = viewer.entities.add({
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(116.8, 36.1, 116.9, 36.2),
outline: true,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 4
}
});
这段代码会在经纬度(116.8,36.1)到(116.9,36.2)的范围内绘制一个带白色边框的矩形。outline参数控制是否显示边框,outlineColor和outlineWidth则分别设置边框颜色和宽度。
当我们需要把平面图形升级为立体图形时,关键在于掌握几个高度相关的参数。这些参数就像是给平面图形"注入"了第三个维度,让它们能够拔地而起。
最常用的高度参数有三个:
举个例子,如果我们想把一个矩形变成立方体,只需要添加extrudedHeight参数:
javascript复制const cube = viewer.entities.add({
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(-118.0, 38.0, -116.0, 40.0),
extrudedHeight: 500000.0,
material: Cesium.Color.BLUE.withAlpha(0.5)
}
});
这个立方体会从地面一直延伸到50万米的高度。在实际项目中,这个高度值通常是根据实际数据换算得到的,比如建筑高度、地形高度等。
除了基本的立方体,Cesium还支持更多复杂的几何体,比如圆柱体、椎体、星形柱等。这些几何体的绘制稍微复杂一些,但原理都是相通的。
以圆柱体为例,我们需要指定顶部半径、底部半径和高度:
javascript复制const cylinder = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-70.0, 45.0, 100000.0),
cylinder: {
length: 200000.0,
topRadius: 150000.0,
bottomRadius: 150000.0,
material: Cesium.Color.RED
}
});
有趣的是,如果把顶部半径设为0,圆柱体就变成了椎体:
javascript复制const cone = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-70.0, 40.0, 200000.0),
cylinder: {
length: 400000.0,
topRadius: 0.0,
bottomRadius: 200000.0,
material: Cesium.Color.GREEN
}
});
在实际项目中,我经常用这种技巧来创建各种特殊形状的建筑模型,比如锥形屋顶、塔楼等。
当我们需要创建大量相似图形时,比如一片建筑群,逐一定义每个实体显然效率太低。这时候可以使用循环来批量创建:
javascript复制for (let i = 0; i < 10; i++) {
const height = 100000.0 + 50000.0 * i;
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-115.0 + i*0.5, 35.0, height),
box: {
dimensions: new Cesium.Cartesian3(80000.0, 80000.0, 80000.0),
material: Cesium.Color.fromRandom({ alpha: 0.8 })
}
});
}
这段代码会创建10个高度递增的立方体,形成一个建筑群的效果。在实际的智慧城市项目中,我经常用这种方法来模拟城市天际线。
另一个高级技巧是组合多种图形来创建复杂模型。比如,可以用一个立方体作为建筑主体,再加上一个椎体作为屋顶:
javascript复制// 建筑主体
const building = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-117.5, 34.0, 0),
box: {
dimensions: new Cesium.Cartesian3(150000.0, 150000.0, 300000.0),
material: Cesium.Color.GRAY
}
});
// 屋顶
const roof = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-117.5, 34.0, 300000.0),
cylinder: {
length: 100000.0,
topRadius: 0.0,
bottomRadius: 100000.0,
material: Cesium.Color.RED
}
});
这种组合方式可以创造出各种富有特色的建筑模型,非常适合用于城市三维可视化。
让我们把这些技巧综合运用到一个智慧城市沙盘的案例中。假设我们要创建一个包含以下元素的场景:
首先创建地面区域:
javascript复制// 商业区
const commercialArea = viewer.entities.add({
polygon: {
hierarchy: new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromDegreesArray([
-118.3, 34.0,
-118.1, 34.0,
-118.1, 34.2,
-118.3, 34.2
])
),
material: Cesium.Color.BLUE.withAlpha(0.3)
}
});
// 住宅区
const residentialArea = viewer.entities.add({
polygon: {
hierarchy: new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromDegreesArray([
-118.3, 34.2,
-118.1, 34.2,
-118.1, 34.4,
-118.3, 34.4
])
),
material: Cesium.Color.GREEN.withAlpha(0.3)
}
});
然后添加一些建筑:
javascript复制// 商业大厦
const officeTower = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-118.2, 34.1, 0),
box: {
dimensions: new Cesium.Cartesian3(50000.0, 50000.0, 200000.0),
material: Cesium.Color.GLASS
}
});
// 居民楼
for (let i = 0; i < 5; i++) {
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-118.2 + i*0.02, 34.3, 0),
box: {
dimensions: new Cesium.Cartesian3(30000.0, 30000.0, 100000.0),
material: Cesium.Color.fromRandom({ alpha: 0.7 })
}
});
}
最后添加一些地标建筑:
javascript复制// 水塔
const waterTower = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-118.25, 34.15, 0),
cylinder: {
length: 50000.0,
topRadius: 10000.0,
bottomRadius: 20000.0,
material: Cesium.Color.WHITE
}
});
// 体育馆
const stadium = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-118.15, 34.25, 0),
ellipse: {
semiMinorAxis: 80000.0,
semiMajorAxis: 120000.0,
extrudedHeight: 50000.0,
material: new Cesium.StripeMaterialProperty({
evenColor: Cesium.Color.WHITE,
oddColor: Cesium.Color.RED
})
}
});
通过这些代码的组合,我们就能创建一个生动形象的智慧城市三维沙盘。在实际项目中,这些图形参数通常是从GIS数据或建筑信息模型中动态生成的,但基本原理都是一样的。