Cesium3d tiles模型单体化思路
首先,当我们把倾斜摄影模型或者建筑模型等osgb、kml等格式的数据转化成b3dm格式之后我们才可以考虑在cesium中做单体化。
cesium中的模型单体化也就是针对于批量的数据的(b3dm)这样的格式。
在查看代码的时候可以多看看注释,有的地方详细解析了为什么要这么做
我们来剖析一下官网提供的思路:
1.建立场景
//创建初始的container并且提供地形
var viewer = new Cesium.Viewer("cesiumContainer", {
terrainProvider: Cesium.createWorldTerrain(),
});
//开启深度检测
viewer.scene.globe.depthTestAgainstTerrain = true;
// 设置相机的观察位置和角度
var initialPosition = Cesium.Cartesian3.fromDegrees(
-74.01881302800248,
40.69114333714821,
753
);
var initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(
21.27879878293835,
-21.34390550872461,
0.0716951918898415
);
viewer.scene.camera.setView({
destination: initialPosition,
orientation: initialOrientation,
endTransform: Cesium.Matrix4.IDENTITY,
});
2.加载数据
// 加载3d tiles数据
var tileset = new Cesium.Cesium3DTileset({
url: Cesium.IonResource.fromAssetId(75343),
});
viewer.scene.primitives.add(tileset);
3.设置鼠标移动事件和鼠标点击事件,当鼠标滑过,或者点击的时候做一些事情
var clickHandler = viewer.screenSpaceEventHandler.getInputAction(
Cesium.ScreenSpaceEventType.LEFT_CLICK
);
4.通过isSilhouetteSupported来判断是否支持轮廓化要素,对要素的轮廓线进行设置
//当要素支持轮廓的时候,设置成鼠标滑过轮廓显示蓝色,单击时显示绿色
//如果要素不支持轮廓,鼠标滑过时要素显示黄色
if (
Cesium.PostProcessStageLibrary.isSilhouetteSupported(viewer.scene)
) {
// 支持轮廓的时候,设置样式
var silhouetteBlue = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
silhouetteBlue.uniforms.color = Cesium.Color.BLUE;
silhouetteBlue.uniforms.length = 0.01;
silhouetteBlue.selected = [];
var silhouetteGreen = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
silhouetteGreen.uniforms.color = Cesium.Color.LIME;
silhouetteGreen.uniforms.length = 0.01;
silhouetteGreen.selected = [];
viewer.scene.postProcessStages.add(
Cesium.PostProcessStageLibrary.createSilhouetteStage([
silhouetteBlue,
silhouetteGreen,
])
);
// 当鼠标滑过时设置蓝色
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
// 如果一个要素此时正处于高亮状态,则取消
silhouetteBlue.selected = [];
5.通过关键的scene.pick()方法获取要素以及属性
// 选择一个新的feature通过场景的pick方法获取
var pickedFeature = viewer.scene.pick(movement.endPosition);
//如果没有要素,则不显示弹框
if (!Cesium.defined(pickedFeature)) {
nameOverlay.style.display = "none";
return;
}
// 如果被选中了,就展示弹框,获取要素的BIN属性展示在弹框内
nameOverlay.style.display = "block";
nameOverlay.style.bottom =
viewer.canvas.clientHeight - movement.endPosition.y + "px";
nameOverlay.style.left = movement.endPosition.x + "px";
var name = pickedFeature.getProperty("BIN");
nameOverlay.textContent = name;
var featureName = pickedFeature.getProperty("name");
selectedEntity.name = featureName;
selectedEntity.description =
'Loading <div class="cesium-infoBox-loading"></div>';
viewer.selectedEntity = selectedEntity;
selectedEntity.description =
'<table class="cesium-infoBox-defaultTable"><tbody>' +
"<tr><th>BIN</th><td>" +
pickedFeature.getProperty("BIN") +
"</td></tr>" +
"<tr><th>DOITT ID</th><td>" +
pickedFeature.getProperty("DOITT_ID") +
"</td></tr>" +
"<tr><th>SOURCE ID</th><td>" +
pickedFeature.getProperty("SOURCE_ID") +
"</td></tr>" +
"</tbody></table>";
scene.pick()方法是用来选择场景中的要素的。通常会返回一个具有“primitive”属性的对象。
但是官方对于scene.pick()方法有这样一句关键的话:
When a feature of a 3D Tiles tileset is picked, pick
returns a Cesium3DTileFeature
object.、
意思是说如果被选中的要素是一个3d tiles的要素,将会返回3d tiles feature对象
实际上,3d tiles feature就是一个特殊的feature,它有着自己独特的属性和方法。
6.3d tilesetfeature的关键方法——getProperty获取要素属性
通过查阅API发现,3d tilesetfeature有一个很关键的方法叫做getProperty()它用来获取要素的属性信息,参数是属性名。
7.要注意3d tiles概念当中提到的每一个模型都是一个feature。
之前讲解3dtiles的时候有一个很重要的概念就是在3d tiles中每一个模型都是一个要素(feature),在这里正是应用了这一点。scene.pick()方法正好能够选择其中的单个要素,这是单体化的关键所在。
8.HTML功底,弹窗跟随鼠标
关键步骤清楚了以后,剩余的就是各位的html和js功底了,想要什么样的弹框,什么样的样式展示属性就是各位来定义了。