前面介绍了Cesium如何加载影像数据、地形数据、以及矢量数据,但是作为一个完整的三维系统,仅仅包括这些数据还是远远不够的。当然,还需要一些其他数据,比如空间可视化数据、三维数据数据等,今天我们先从空间数据的可视化说起,后面会有专门的章节介绍三维数据方面的加载。
Cesium在空间数据可视化方面提供了两种类型的API,一种是面向图形开发人员的低级(原始)API,通过Primitive类实现,对于那些对计算机图形学知识很了解的同学可以采用Primitive API,后面章节会有详细介绍;另一种是用于数据驱动的高级(实体)API,通过Entity类实现,相对于Primitive API,Entity API实现起来更简单一些,特别建议初学者使用。Entity API 实际上是对Primitive API的二次封装,底层调用的仍然是Primitive API,目的就是为我们提供灵活的、易学、易用的高性能可视化界面。本章节内容主要介绍后者Entity API,Primitive API放在后面的高级篇里讲解。
Entity支持的图形类型
通过在Cesium API文档中查看Entity类的构造函数,我们发现Entity支持的图形类型都是以Graphics结尾的,一共有17种类型。如下图所示,列出了Entity支持的图形类型以及对应的js类。
下面,简单介绍一下每一种类型的Graphic添加方式。
1)billboard 广告牌
var entity = viewer.entities.add({
// id: "",
name: "billboard",
// show: true,
// description: "",
// orientation: "",
position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
billboard: {
show: true, // default
image: "./images/Cesium_Logo_overlay.png", // default: undefined
scale: 2.0, // default: 1.0
//像素偏移 type: Cartesian2 default:Cartesian2.ZERO
pixelOffset: new Cesium.Cartesian2(0, -50),
//眼睛偏移 type: Cartesian3 default:Cartesian3.ZERO
eyeOffset: new Cesium.Cartesian3(0.0, 0.0, 0.0),
// 水平对齐方式 type: HorizontalOrigin default:HorizontalOrigin.CENTER
// CENTER 原点在对象的水平中心;LEFT 原点在对象的左侧;RIGHT 原点在对象的右侧
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
// 垂直对齐方式 type: VerticalOrigin default:VerticalOrigin.CENTER
// CENTER 原点位于 BASELINE 和 TOP 之间的垂直中心;BOTTOM 原点在对象的底部;
// BASELINE 如果对象包含文本,则原点位于文本的基线,否则原点位于对象的底部;TOP 原点在对象的顶部
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // default: CENTER 垂直对齐位置 参考Cesium.VerticalOrigin
// 获取或设置此广告牌的高度参考 type: HeightReference default:HeightReference.NONE
// NONE 位置绝对;CLAMP_TO_GROUND 位置固定在地形上;RELATIVE_TO_GROUND 位置高度是指地形上方的高度
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
// 颜色 type: Color default:Color.WHITE
color: Cesium.Color.LIME,
// 获取或设置以弧度为单位的旋转角度 type: number default:0
rotation: Cesium.Math.PI_OVER_FOUR,
// 获取或设置世界空间中的对齐轴 type:Cartesian3 default:Cartesian3.ZERO
alignedAxis: Cesium.Cartesian3.ZERO,
width: 100, // default: undefined
height: 25, // default: undefined
// 根据广告牌与相机的距离获取或设置广告牌的近和远缩放属性 type:NearFarScalar
scaleByDistance: new Cesium.NearFarScalar(1.0e3, 2.0, 2.0e3, 1.0),
// 根据广告牌到相机的距离,获取或设置广告牌的近和远半透明属性 type:NearFarScalar
translucencyByDistance: new Cesium.NearFarScalar(
1.0e3,
1.0,
1.5e6,
0.5
),
// 根据广告牌与摄像头的距离,获取或设置广告牌的近像素偏移量和远像素偏移量缩放属性 type:NearFarScalar
pixelOffsetScaleByDistance: new Cesium.NearFarScalar(
1.0e3,
1.0,
1.5e6,
0.0
),
// 设置1000米和2000米之间可见 type:DistanceDisplayCondition
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
// 获取或设置与相机的距离,在深度处禁用深度测试,例如,以防止剪切地形。
// 设置为零时,将始终应用深度测试。设置为Number.POSITIVE_INFINITY时,永远不会应用深度测试。
disableDepthTestDistance: Number.POSITIVE_INFINITY,
},
});
2)box 盒子
var entity = viewer.entities.add({
name: "box",
position: Cesium.Cartesian3.fromDegrees(-107.0, 40.0, 300000.0),
box: {
show: true,
dimensions: new Cesium.Cartesian3(400000.0, 300000.0, 500000.0), // Cartesian3类型,用于指定框的长度,宽度和高度
// 指定距实体位置的高度是相对于什么的高度。 default: HeightReference.NONE
// NONE 位置绝对;CLAMP_TO_GROUND 位置固定在地形上;RELATIVE_TO_GROUND 位置高度是指地形上方的高度。
heightReference: Cesium.HeightReference.NONE,
fill: true,
// MaterialProperty|Color default:Color.WHITE
material: Cesium.Color.RED.withAlpha(0.5),
outline: true,
// type:Property|Color default:Color.BLACK
outlineColor: Cesium.Color.BLACK,
outlineWidth: 1.0,
// type:ShadowMode default:ShadowMode.DISABLED
// DISABLED 对象不投射或接收阴影;ENABLED 对象投射并接收阴影;CAST_ONLY 对象仅投射阴影;RECEIVE_ONLY 该对象仅接收阴影。
shadows: Cesium.ShadowMode.DISABLED,
// type:DistanceDisplayCondition
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
},
});
3)corridor 走廊
var entity = viewer.entities.add({
name: "corridor",
corridor: {
// show: true,
// 指定定义走廊中心线的 Cartesian3 位置的数组 type: Cartesian3
positions: Cesium.Cartesian3.fromDegreesArray([
-80.0,
40.0,
-85.0,
40.0,
-85.0,
35.0,
]),
width: 200000.0,
height: 200000.0,
heightReference: Cesium.HeightReference.NONE,
extrudedHeight: 100000.0,
extrudedHeightReference: Cesium.HeightReference.NONE,
// 拐角的样式 type:CornerType default:CornerType.ROUNDED
// ROUNDED 角有光滑的边缘;MITERED 拐角点是相邻边的交点;BEVELED 角被修剪
cornerType: Cesium.CornerType.ROUNDED,
granularity: Cesium.Math.RADIANS_PER_DEGREE, // 每个纬度和经度之间的距离
fill: true,
// 材质 type:MaterialProperty|Color default:Color.WHITE
material: Cesium.Color.BLUE.withAlpha(0.5),
outline: true, // height or extrudedHeight must be set for outlines to display
outlineColor: Cesium.Color.WHITE,
outlineWidth: 1.0,
shadows: Cesium.ShadowMode.DISABLED,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
// 走廊在地面上时将对地形,3D tiles还是对两者进行分类 type:ClassificationType default:ClassificationType.BOTH
// TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH 将同时对Terrain和3D Tiles进行分类。
classificationType: Cesium.ClassificationType.BOTH,
},
});
4)cylinder 圆柱、圆锥
var entity = viewer.entities.add({
name: "cylinder",
position: Cesium.Cartesian3.fromDegrees(-105.0, 40.0, 200000.0),
cylinder: {
// show: true,
length: 400000.0, // 圆柱体长度
topRadius: 200000.0, // 圆柱体顶部半径
bottomRadius: 200000.0, // 圆柱体底部半径
heightReference: Cesium.HeightReference.NONE,
fill: true,
material: Cesium.Color.GREEN.withAlpha(0.5),
outline: true,
outlineColor: Cesium.Color.DARK_GREEN,
outlineWidth: 1.0,
numberOfVerticalLines: 16, // 沿轮廓的周长绘制的垂直线的数量
shadows: Cesium.ShadowMode.DISABLED,
slices: 128, // 圆柱周围的边缘数量
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
},
});
5)ellipse 椭圆或拉伸的椭圆
var entity = viewer.entities.add({
name: "Circles and Ellipses",
position: Cesium.Cartesian3.fromDegrees(-95.0, 40.0, 100000.0),
ellipse: {
show: true,
semiMajorAxis: 300000.0, // 长半轴距离
semiMinorAxis: 150000.0, // 短半轴距离
height: 20000.0,
heightReference: Cesium.HeightReference.NONE,
extrudedHeight: 20000.0,
extrudedHeightReference: Cesium.HeightReference.NONE,
// rotation: Cesium.Math.toRadians(45), // 从北方逆时针旋转
stRotation: 0.0, // 纹理从北方逆时针旋转
granularity: Cesium.Math.RADIANS_PER_DEGREE, // 椭圆上各点之间的角距离
material: Cesium.Color.BLUE.withAlpha(0.5),
fill: true,
outline: true,
outlineColor: Cesium.Color.DARK_GREEN,
outlineWidth: 1.0,
numberOfVerticalLines: 16, // 沿轮廓的周长绘制的垂直线的数量
shadows: Cesium.ShadowMode.DISABLED,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
// 在地面上时将对地形,3D tiles还是对两者进行分类 type:ClassificationType default:ClassificationType.BOTH
// TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D瓷砖进行分类;BOTH 将同时对Terrain和3D Tile进行分类。
classificationType: Cesium.ClassificationType.BOTH,
},
});
6)ellipsoid 椭球体
var entity = viewer.entities.add({
name: "Spheres and Ellipsoids",
position: Cesium.Cartesian3.fromDegrees(-100.0, 40.0, 300000.0),
ellipsoid: {
show: true,
radii: new Cesium.Cartesian3(200000.0, 200000.0, 300000.0), // 椭球半径
// innerRadii: new Cesium.Cartesian3(0.0, 0.0, 0.0), // 椭球内部半径
minimumClock: 0.0, // 最小时钟角度
maximumClock: 2 * Math.PI, // 最大时钟角度
minimumCone: 0.0, // 最小圆锥角
maximumCone: Math.PI, // 最大圆锥角
heightReference: Cesium.HeightReference.NONE,
fill: true,
material: Cesium.Color.BLUE.withAlpha(0.5),
outline: true,
outlineColor: Cesium.Color.YELLOW,
outlineWidth: 1.0,
stackPartitions: 64, // 延纬度线切割的次数
slicePartitions: 64, // 延经度线切割的次数
subdivisions: 128, // 每个轮廓环的样本数,确定曲率的粒度
shadows: Cesium.ShadowMode.DISABLED,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
},
});
7)label 标签
var entity = viewer.entities.add({
name: "label",
position: Cesium.Cartesian3.fromDegrees(
-75.1641667,
39.9522222,
300000.0
),
label: {
show: true,
text: "label标签",
font: "24px Helvetica",
// FILL 填充;OUTLINE 只显示边框;FILL_AND_OUTLINE 既有填充又有边框
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
scale: 1.0,
showBackground: true,
backgroundColor: Cesium.Color.BLUE,
backgroundPadding: new Cartesian2(7, 5),
pixelOffset: Cartesian2.ZERO,
eyeOffset: Cartesian3.ZERO,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
heightReference: Cesium.HeightReference.NONE,
fillColor: Cesium.Color.SKYBLUE,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
translucencyByDistance: new Cesium.NearFarScalar(
1.0e3,
1.0,
1.5e6,
0.5
),
pixelOffsetScaleByDistance: new Cesium.NearFarScalar(
1.0e3,
1.0,
1.5e6,
0.0
),
scaleByDistance: new Cesium.NearFarScalar(1.0e3, 2.0, 2.0e3, 1.0),
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
disableDepthTestDistance: Number.POSITIVE_INFINITY,
},
});
8)model 模型
var position = Cesium.Cartesian3.fromDegrees(
-123.0744619,
44.0503706,
5000.0
);
var heading = Cesium.Math.toRadians(135);
var pitch = 0;
var roll = 0;
var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
hpr
);
var url = "./data/models/CesiumAir/Cesium_Air.glb";
var entity = viewer.entities.add({
name: "model",
position: position,
orientation: orientation,
model: {
show: true,
uri: url,
scale: 1.0,
minimumPixelSize: 128, // 模型的最小最小像素大小,而不考虑缩放
maximumScale: 20000, // 模型的最大比例尺大小。 minimumPixelSize的上限
incrementallyLoadTextures: true, // 确定在加载模型后纹理是否可以继续流入
runAnimations: true, // 是否应启动模型中指定的glTF动画
clampAnimations: true, // glTF动画是否应在没有关键帧的持续时间内保持最后一个姿势
shadows: Cesium.ShadowMode.DISABLED,
heightReference: Cesium.HeightReference.NONE,
silhouetteColor: Cesium.Color.RED, // 轮廓的颜色
silhouetteSize: 0.0, // 轮廓的宽度
color: Cesium.Color.WHITE, // 模型的颜色
// 目标颜色和图元的源颜色之间混合的不同模式
// HIGHLIGHT 将源颜色乘以目标颜色;REPLACE 将源颜色替换为目标颜色;MIX 将源颜色和目标颜色混合在一起
colorBlendMode: Cesium.ColorBlendMode.HIGHLIGHT,
// 用于指定 colorBlendMode 为 MIX 时的颜色强度。值0.0会产生模型的着色,而值1.0会导致纯色,介于两者之间的任何值都会导致两者混合
colorBlendAmount: 0.5,
imageBasedLightingFactor: new Cesium.Cartesian2(1.0, 1.0), // 指定基于漫反射和镜面反射的图像照明的贡献
lightColor: undefined, // 为模型着色时指定浅色的属性。如果 undefined ,则使用场景的浅色。
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
},
});
9)tileset 3D Tiles瓦片集
var tileset = viewer.entities.add({
name: "3D Tiles",
position: Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0),
tileset: {
show: true,
uri: new Cesium.Plane(Cesium.Cartesian3.UNIT_X, 0.0),
},
});
10)path 路径
var entityPath = viewer.entities.add({
position: pathPosition,
name: "path",
path: {
show: true,
leadTime: 0,
trailTime: 60,
width: 10,
resolution: 1,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.3,
taperPower: 0.3,
color: Cesium.Color.PALEGOLDENROD,
}),
},
});
11)plane 平面
var bluePlane = viewer.entities.add({
name: "Blue plane",
position: Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0),
plane: {
show: true,
// 用于指定平面的法线和距离
plane: new Cesium.Plane(Cesium.Cartesian3.UNIT_X, 0.0),
dimensions: new Cesium.Cartesian2(400000.0, 300000.0), // 指定平面的宽度和高度
fill: true,
material: Cesium.Color.BLUE,
outline: false,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 1.0,
shadows: Cesium.ShadowMode.DISABLED,
// type:DistanceDisplayCondition
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
},
});
12)point 点
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
point: {
show: true,
pixelSize: 10, // 像素大小
heightReference: Cesium.HeightReference.NONE,
color: Cesium.Color.YELLOW,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 0,
scaleByDistance: new Cesium.NearFarScalar(1.0e3, 10.0, 2.0e3, 1.0),
translucencyByDistance: new Cesium.NearFarScalar(
1.0e3,
1.0,
1.5e6,
0.5
),
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
// 获取或设置与相机的距离,在深度处禁用深度测试,例如,以防止剪切地形。
// 设置为零时,将始终应用深度测试。设置为Number.POSITIVE_INFINITY时,永远不会应用深度测试。
disableDepthTestDistance: Number.POSITIVE_INFINITY,
},
});
13)polygon 多边形
var redPolygon = viewer.entities.add({
name: "Red polygon on surface",
polygon: {
show: true,
// 指定PolygonHierarchy
hierarchy: Cesium.Cartesian3.fromDegreesArray([
-115.0,
37.0,
-115.0,
32.0,
-107.0,
33.0,
-102.0,
31.0,
-102.0,
35.0,
]),
height: 0, // 多边形相对于椭球面的高度
heightReference: Cesium.HeightReference.NONE,
// extrudedHeight: 0, // 多边形的凸出面相对于椭球面的高度
// extrudedHeightReference: Cesium.HeightReference.NONE,
stRotation: 0.0, // 多边形纹理从北方逆时针旋转
granularity: Cesium.Math.RADIANS_PER_DEGREE, // 每个纬度和经度点之间的角距离
fill: true,
material: Cesium.Color.RED,
outline: false,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 1.0,
perPositionHeight: false, // 是否使用每个位置的高度
closeTop: true, // 如果为false,则将挤出的多边形顶部留空
closeBottom: true, // 如果为false,则将挤出的多边形的底部保留为开放状态
// 多边形边缘必须遵循的线型 type:ArcType 定义连接顶点应采用的路径。
// NONE 与椭圆表面不符的直线;GEODESIC 遵循测地路径;RHUMB 遵循大黄蜂或恶魔般的道路。
arcType: Cesium.ArcType.GEODESIC,
shadows: Cesium.ShadowMode.DISABLED,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
// 在地面上时将对地形,3D tiles还是对两者进行分类 type:ClassificationType default:ClassificationType.BOTH
// TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH 将同时对Terrain和3D Tiles进行分类。
classificationType: Cesium.ClassificationType.BOTH,
// 指定用于订购地面几何形状的z索引。仅在多边形为常数且未指定高度或拉伸高度的情况下才有效 type:ConstantProperty
zIndex: 0,
},
});
14)polyline 多线段
var redLine = viewer.entities.add({
name: "Red line on terrain",
polyline: {
show: true,
// 定义线条的 Cartesian3 位置的数组
positions: Cesium.Cartesian3.fromDegreesArray([-75, 35, -125, 35]),
width: 5,
// 如果arcType不是ArcType.NONE,则指定每个纬度和经度之间的角距离
// granularity: Cesium.Math.RADIANS_PER_DEGREE,
material: Cesium.Color.RED,
// 线低于地形时用于绘制折线的材质
// depthFailMaterial: Cesium.Color.WHITE,
// 折线段必须遵循的线型
// arcType: Cesium.ArcType.GEODESIC,
clampToGround: true, // 是否贴地
shadows: Cesium.ShadowMode.DISABLED, // 折线是投射还是接收光源的阴影
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
// 在地面上时将对地形,3D tiles还是对两者进行分类 type:ClassificationType default:ClassificationType.BOTH
// TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH 将同时对Terrain和3D Tiles进行分类。
classificationType: Cesium.ClassificationType.BOTH,
// 指定用于订购地面几何形状的z索引。仅在多边形为常数且未指定高度或拉伸高度的情况下才有效 type:ConstantProperty
// zIndex: 0,
},
});
15)polylineVolume 多线段柱体
function computeCircle(radius) {
var positions = [];
for (var i = 0; i < 360; i++) {
var radians = Cesium.Math.toRadians(i);
positions.push(
new Cesium.Cartesian2(
radius * Math.cos(radians),
radius * Math.sin(radians)
)
);
}
return positions;
}
var redTube = viewer.entities.add({
name: "Red tube with rounded corners",
polylineVolume: {
show: true,
// 定义线带的 Cartesian3 位置的数组
positions: Cesium.Cartesian3.fromDegreesArray([
-85.0,
32.0,
-85.0,
36.0,
-89.0,
36.0,
]),
// 指定 Cartesian2 位置的数组,这些位置定义了要拉伸的形状
shape: computeCircle(60000.0),
// 拐角的样式 type:CornerType
// ROUNDED 拐角有光滑的边缘;MITERED 拐角点是相邻边的交点;BEVELED 拐角被修剪。
cornerType: Cesium.CornerType.ROUNDED,
// 如果arcType不是ArcType.NONE,则指定每个纬度和经度之间的角距离
// granularity: Cesium.Math.RADIANS_PER_DEGREE,
fill: true,
material: Cesium.Color.RED,
outline: false,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 1.0,
shadows: Cesium.ShadowMode.DISABLED, // 体积是投射还是接收光源的阴影
// type:DistanceDisplayCondition
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
},
});
16)rectangle 矩形
var redRectangle = viewer.entities.add({
name: "Red translucent rectangle",
rectangle: {
show: true,
coordinates: Cesium.Rectangle.fromDegrees(-110.0, 20.0, -80.0, 25.0),
// height: 0, // 矩形相对于椭球面的高度
// heightReference: Cesium.HeightReference.NONE,
// extrudedHeight: 0, // 矩形的拉伸面相对于椭球面的高度
// extrudedHeightReference: Cesium.HeightReference.NONE,
rotation: 0.0, // 矩形从北方向顺时针方向的旋转
stRotation: 0.0, // 矩形纹理从北方逆时针旋转
granularity: Cesium.Math.RADIANS_PER_DEGREE, // 指定矩形上各点之间的角度距离
fill: true,
material: Cesium.Color.RED.withAlpha(0.5),
outline: false,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 1.0,
shadows: Cesium.ShadowMode.DISABLED,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
// 在地面上时将对地形,3D tiles还是对两者进行分类 type:ClassificationType default:ClassificationType.BOTH
// TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH 将同时对Terrain和3D Tiles进行分类。
classificationType: Cesium.ClassificationType.BOTH,
// 指定用于订购地面几何形状的z索引。仅在多边形为常数且未指定高度或拉伸高度的情况下才有效 type:ConstantProperty
zIndex: 0,
},
});
17)wall 墙
var redWall = viewer.entities.add({
name: "Red wall at height",
wall: {
show: true,
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
-115.0,
44.0,
200000.0,
-90.0,
44.0,
200000.0,
]),
// 用于墙底而不是地球表面的高度数组
minimumHeights: [100000.0, 100000.0],
// 用于墙顶的高度数组,而不是每个位置的高度
// maximumHeights: [],
granularity: Cesium.Math.RADIANS_PER_DEGREE, // 指定矩形上各点之间的角度距离
fill: true,
material: Cesium.Color.RED,
outline: false,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 1.0,
shadows: Cesium.ShadowMode.DISABLED,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0e3,
// 2.0e3
// ),
},
});
Entity 聚合
同时,针对Billboard、Label、Point,Cesium 提供了 EntityCluster 类用于实现聚合效果,但必须结合 PinBuilder 类实现。下面为实现聚合效果的核心代码:
var options = {
camera: viewer.scene.camera,
canvas: viewer.scene.canvas,
};
var dataSourcePromise = viewer.dataSources.add(
Cesium.KmlDataSource.load("./data/kml/facilities/facilities.kml", options)
);
dataSourcePromise.then(function (dataSource) {
var pixelRange = 15;
var minimumClusterSize = 3;
var enabled = true;
dataSource.clustering.enabled = enabled;
dataSource.clustering.pixelRange = pixelRange; // 扩展屏幕空间边界框的像素范围
dataSource.clustering.minimumClusterSize = minimumClusterSize; // 可以聚合的最小屏幕空间对象
var removeListener;
var pinBuilder = new Cesium.PinBuilder();
var pin50 = pinBuilder.fromText("50+", Cesium.Color.RED, 48).toDataURL();
var pin40 = pinBuilder
.fromText("40+", Cesium.Color.ORANGE, 48)
.toDataURL();
var pin30 = pinBuilder
.fromText("30+", Cesium.Color.YELLOW, 48)
.toDataURL();
var pin20 = pinBuilder
.fromText("20+", Cesium.Color.GREEN, 48)
.toDataURL();
var pin10 = pinBuilder.fromText("10+", Cesium.Color.BLUE, 48).toDataURL();
var singleDigitPins = new Array(8);
for (var i = 0; i < singleDigitPins.length; ++i) {
singleDigitPins[i] = pinBuilder
.fromText("" + (i + 2), Cesium.Color.VIOLET, 48)
.toDataURL();
}
function customStyle() {
if (Cesium.defined(removeListener)) {
removeListener();
removeListener = undefined;
} else {
removeListener = dataSource.clustering.clusterEvent.addEventListener(
function (clusteredEntities, cluster) {
cluster.label.show = false;
cluster.billboard.show = true;
cluster.billboard.id = cluster.label.id;
cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
if (clusteredEntities.length >= 50) {
cluster.billboard.image = pin50;
} else if (clusteredEntities.length >= 40) {
cluster.billboard.image = pin40;
} else if (clusteredEntities.length >= 30) {
cluster.billboard.image = pin30;
} else if (clusteredEntities.length >= 20) {
cluster.billboard.image = pin20;
} else if (clusteredEntities.length >= 10) {
cluster.billboard.image = pin10;
} else {
cluster.billboard.image =
singleDigitPins[clusteredEntities.length - 2];
}
}
);
}
// force a re-cluster with the new styling
var pixelRange = dataSource.clustering.pixelRange;
dataSource.clustering.pixelRange = 0;
dataSource.clustering.pixelRange = pixelRange;
}
// start with custom style
customStyle();
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
var pickedLabel = viewer.scene.pick(movement.position);
if (Cesium.defined(pickedLabel)) {
var ids = pickedLabel.id;
if (Array.isArray(ids)) {
for (var i = 0; i < ids.length; ++i) {
ids[i].billboard.color = Cesium.Color.RED;
}
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
});
Entity 管理
上面介绍了Entity的图形类型,有这么多类型的实体,Cesium是如何管理这些实体对象的呢,这就需要我们从初始化Viewer对象开始说起了。当我们初始化Viewer类之后,会得到一个实例化对象viewer,这个viewer会包含一个属性 entities ,它的类型是 EntityCollection ,也就是 Entity 的集合,它包括了 EntityCollection 类里面的所有属性和方法。所以 Cesium 管理 Entity 本质上是通过 EntityCollection 类进行管理的,比如add(添加Entity)、contains(是否存在某个Entity)、getById(通过ID获取Entity)、remove(移除某个Entity)、removeAll(移除所有的Entity)、removeById(通过ID移除Entity)方法等。
var point = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-105.0, 41, 50010),
point: {
show: true,
pixelSize: 10, // 像素大小
},
});
var entity = viewer.entities.getById("entity_1");
viewer.entities.remove(entity);
// viewer.entities.removeById("entity_1");
// viewer.entities.removeAll();
Entity 拾取
在三维场景种,很常见的一种交互方式,就是鼠标点击三维场景种某一个几何图形,查看该图形的包含的属性信息,并显示在对应的信息窗体中。单击事件通过 ScreenSpaceEventHandler 类注册,拾取到的信息可通过以下两种方式获取。
- scene.pick:获取窗体坐标处最顶部的实体;
- scene.drillPick:窗体坐标处的实体列表。
// 添加拾取事件
var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(function (movement) {
var pickedEntity = pickEntity(viewer, movement.position);
console.log(pickedEntity);
var pickedEntities = drillPickEntities(viewer, movement.position);
console.log(pickedEntities);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
function pickEntity(viewer, windowPosition) {
var picked = viewer.scene.pick(windowPosition);
if (Cesium.defined(picked)) {
var id = Cesium.defaultValue(picked.id, picked.primitive.id);
if (id instanceof Cesium.Entity) {
return id;
}
}
return undefined;
}
function drillPickEntities(viewer, windowPosition) {
var i;
var entity;
var picked;
var pickedPrimitives = viewer.scene.drillPick(windowPosition);
var length = pickedPrimitives.length;
var result = [];
var hash = {};
for (i = 0; i < length; i++) {
picked = pickedPrimitives[i];
entity = Cesium.defaultValue(picked.id, picked.primitive.id);
if (
entity instanceof Cesium.Entity &&
!Cesium.defined(hash[entity.id])
) {
result.push(entity);
hash[entity.id] = true;
}
}
return result;
}
Entity 固定
在实际的应用系统中,会有这样的需求,要求画的实体附着在地形表面、或三维建筑表面(比如视频融合),这时候就需要设置xxGraphics的相关属性了,可通过 heightReference 或 classificationType 这两个属性去控制。属性值描述如下:
heightReference属性值:
NONE:位置绝对(默认值);
CLAMP_TO_GROUND:位置固定在地形上;
RELATIVE_TO_GROUND:位置高度是指地形上方的高度classificationType属性值:
TERRAIN:将仅对地形进行分类;
CESIUM_3D_TILE:将仅对3D Tiles进行分类;
BOTH :将同时对Terrain和3D Tiles进行分类。
其中corridor 、 ellipse 、 polygon 、 polyline 、 rectangle 可通过设置 classificationType 属性值显示仅贴地、仅贴建筑或者两者都贴的效果,billboard 、 box 、 corridor 、 cylinder 、 ellipse 、 ellipsoid 、 label 、 model 、 point 、 polygon 、 tectangle通过设置 heightReference 属性值为 CLAMP_TO_GROUND 显示贴地效果。这里需要注意的是,如果是polyline必须设置 clampToGround 属性为 true 。
// set the heightReference to CLAMP_TO_GROUND
// billboard box corridor cylinder ellipse ellipsoid label model point polygon tectangle
// 其中corridor ellipse polygon retangle会自动贴地
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-122.1958, 46.1915),
billboard: {
image: "./images/facility.gif",
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
point: {
color: Cesium.Color.SKYBLUE,
pixelSize: 10,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
label: {
text: "Clamped to ground",
font: "14pt sans-serif",
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.BASELINE,
fillColor: Cesium.Color.BLACK,
showBackground: true,
backgroundColor: new Cesium.Color(1, 1, 1, 0.7),
backgroundPadding: new Cesium.Cartesian2(8, 4),
disableDepthTestDistance: Number.POSITIVE_INFINITY, // draws the label in front of terrain
},
});
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-122.1958, 46.1915),
model: {
uri: "./data/models/CesiumMan/Cesium_Man.glb",
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
minimumPixelSize: 128,
maximumScale: 100,
},
});
// corridors、ellipse、 polygons and rectangles will be clamped automatically
// if they are filled with a constant color and has no height or extruded height.
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-122.195, 46.1915),
corridor: {
positions: Cesium.Cartesian3.fromDegreesArray([
-122.19,
46.1914,
-122.2,
46.1924,
-122.21,
46.193,
]),
width: 500.0,
material: Cesium.Color.GREEN.withAlpha(0.5),
},
ellipse: {
semiMajorAxis: 300.0, // 长半轴距离
semiMinorAxis: 150.0, // 短半轴距离
// heightReference: Cesium.HeightReference.NONE,
material: Cesium.Color.BLUE.withAlpha(0.5),
// material: "./images/Cesium_Logo_Color.jpg",
// classificationType: Cesium.ClassificationType.BOTH,
},
polygon: {
hierarchy: {
positions: [
new Cesium.Cartesian3(
-2358138.847340281,
-3744072.459541374,
4581158.5714175375
),
new Cesium.Cartesian3(
-2357231.4925370603,
-3745103.7886602185,
4580702.9757762635
),
new Cesium.Cartesian3(
-2355912.902205431,
-3744249.029778454,
4582402.154378103
),
new Cesium.Cartesian3(
-2357208.0209552636,
-3743553.4420488174,
4581961.863286629
),
],
},
// material: Cesium.Color.BLUE.withAlpha(0.5),
material: "./images/Cesium_Logo_Color.jpg",
},
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(-122.2, 46.2, -122.1, 46.3),
material: Cesium.Color.RED.withAlpha(0.5),
},
});
// set the classificationType to TERRAIN
// corridor ellipse polygon polyline rectangle
// 其中polyline 必须 设置clampToGround = true
viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([
-122.1968,
46.1915,
-122.1968,
46.2015,
-122.1968,
46.2015,
]),
clampToGround: true,
width: 5,
material: Cesium.Color.ORANGE,
depthFailMaterial: Cesium.Color.RED,
// classificationType: Cesium.ClassificationType.BOTH,
},
});
var polygon = viewer.entities.add({
polygon: {
hierarchy: new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromRadiansArray([
-1.3194369277314022,
0.6988062530900625,
-1.3193955980204217,
0.6988091578771254,
-1.3193931220959367,
0.698743632490865,
-1.3194358224045408,
0.6987471965556998,
])
),
// NONE 位置绝对;CLAMP_TO_GROUND 位置固定在地形上;RELATIVE_TO_GROUND 位置高度是指地形上方的高度
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
// material: Cesium.Color.RED.withAlpha(0.5),
material: "./images/Cesium_Logo_Color.jpg",
// TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH 将同时对Terrain和3D Tiles进行分类。
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
},
});
var polyline = viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([
-75.60217330403601,
40.04102882709425,
-75.59968252414251,
40.04093615560871,
-75.598020153828,
40.04079437042357,
-75.59674934074435,
40.040816173283304,
-75.59630042791713,
40.03986900370842,
-75.59563636849978,
40.03930996506271,
-75.59492397899098,
40.03873932846581,
-75.59457991226778,
40.038392701955786,
-75.59424838652453,
40.03775403572295,
-75.59387104290336,
40.03677022167725,
-75.59355000490342,
40.03588760913535,
]),
width: 8,
material: new Cesium.PolylineOutlineMaterialProperty({
color: Cesium.Color.YELLOW,
outlineWidth: 2,
outlineColor: Cesium.Color.BLACK,
}),
clampToGround: true,
// TERRAIN 将仅对地形进行分类;CESIUM_3D_TILE 将仅对3D Tiles进行分类;BOTH 将同时对Terrain和3D Tiles进行分类。
classificationType: Cesium.ClassificationType.TERRAIN,
},
});