上一节学习了Primitive加载帖地(3dtiles)的线。如果需要绘制帖3dtiles的体,在CESIUM例子学习(七)——Classification Types中学习了整栋楼的单体化。但是如果要在倾斜摄影中,只单体化某建筑二楼、三楼,该如何绘制呢?其实cesium还提供了另一个对象Cesium.ClassificationPrimitive。它可以通过绘制一个BoxGeometry、EllipsoidGeometry等来实现这样的单体化。
代码很简单,项目中基本上都要鼠标交互,所以需要注意的是在 attributes属性中设置show属性,也就是设置绘制是否在初始化时就起作用。即: attributes: {
……
show: new Cesium.ShowGeometryInstanceAttribute(true),设置初始化后是否显示 }
整个 加载的绘制代码如下:
var buildingHighlight1, buildingHighlight2
function addBoxClassificationPrimitive () {
let length = 39.0, width = 18.0, height = 4.0, baseHeight = -14.5 //楼的长宽高和基地高
let center = { //楼中心点位置
x: -2025016.752089428,
y: 5532291.539549444,
z: 2436368.8372620787
},
modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);
hprRotation = Cesium.Matrix3.fromHeadingPitchRoll(
new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(-6), 0.0, 0.0)
);
hpr = Cesium.Matrix4.fromRotationTranslation(
hprRotation,
new Cesium.Cartesian3(0.0, 0.0, baseHeight) //楼层高度上的偏移
);
Cesium.Matrix4.multiply(modelMatrix, hpr, modelMatrix);
buildingHighlight1 = viewer.scene.primitives.add(
new Cesium.ClassificationPrimitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: Cesium.BoxGeometry.fromDimensions({
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
dimensions: new Cesium.Cartesian3(length, width, height),
}),
modelMatrix: modelMatrix,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
new Cesium.Color(1.0, 0.0, 0.0, 0.5)设置高亮颜色
),
show: new Cesium.ShowGeometryInstanceAttribute(true),设置初始化后是否显示
},
id: "BoxClassificationPrimitive1",
}),
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,//只绘制在3dtiles上
})
);
let modelMatrix2 = Cesium.Transforms.eastNorthUpToFixedFrame(center);
hpr = Cesium.Matrix4.fromRotationTranslation(
hprRotation,
new Cesium.Cartesian3(0.0, 0.0, baseHeight + height)
);
Cesium.Matrix4.multiply(modelMatrix2, hpr, modelMatrix2);
buildingHighlight2 = viewer.scene.primitives.add(
new Cesium.ClassificationPrimitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: Cesium.BoxGeometry.fromDimensions({
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
dimensions: new Cesium.Cartesian3(39.0, 18.0, 4.0),
}),
modelMatrix: modelMatrix2,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
new Cesium.Color(0.0, 1.0, 0.0, 0.5)
),
show: new Cesium.ShowGeometryInstanceAttribute(true),设置初始化后是否显示
},
id: "BoxClassificationPrimitive2",
}),
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,//只绘制在3dtiles上
})
);
}
绘制结果如下图:
图中可以看到最下面一层范围比楼大,是因为这个范围是拖动绘制的。在项目中应该是有其它数据来源。
属性获取与设置是通过GeometryInstance的id进行的,首先需要通过id获取到attributes对象,即:
let attributes= buildingHighlight1.getGeometryInstanceAttributes("BoxClassificationPrimitive1")。代码中getGeometryInstanceAttributes方法要在数据加载完成调用update后过可用,否则会报getGeometryInstanceAttributes的undefined错误。
cesium通过scene.invertClassification属性,设置3dtiles的设置颜色是否起作用; 设置scene.invertClassificationColor颜色控制3dtiles颜色。
属性获取与设置的整个代码如下:
function invertClassification (checked) {
let scene = viewer.scene
if (checked && !scene.invertClassificationSupported) {
window.alert("This browser does not support invert classification");
}
scene.invertClassification = checked;
scene.invertClassificationColor = new Cesium.Color(
0.15,
0.15,
0.15,
1.0,
);
let v = Cesium.ShowGeometryInstanceAttribute.toValue(!checked);
let attr = buildingHighlight1.getGeometryInstanceAttributes("BoxClassificationPrimitive1")
attr.show = v;交互控制高亮与否
attr = buildingHighlight2.getGeometryInstanceAttributes("BoxClassificationPrimitive2")
attr.show = v;交互控制高亮与否
}
在交互中经经常会通过点击之类的操作获取被点击建筑等属性。可以通过在加载高亮盒子时,设置盒子的id,在点击时,通过下面方法获取到点中目标的id。通过这个id获取相应的外部属性。代码如下:
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function (movement) {
checked = !checked
invertClassification(checked)
var pickedObject = scene.pick(movement.position);
if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
modelid=pickedObject.id
}
结果如下图:
EllipsoidGeometry绘制不再作说明,可以参考前一节中的EllipsoidGeometry设置参数,而 classificationType属性与BoxGeometry设置一样。源码例子绘制的结果如下图: