原文链接及内容

Building Explorer面板的下拉框默认选择Overview选项, 效果如下:

注:由于我们在开发中默认不会使用Cesium封装组件(组件的样式方面基本不符合我们的需求),针对该组件的使用,大家可以自行研究,这里不再赘述。

Overview选项

我们还可以在选择Full Model选项, 则可以选择建筑物的某一部分(层次), 具体如下所示:

Full Model选项

示例代码如下:

注:关于I3S(Index 3D Scene)请参考文章:https://cesium.com/blog/2023/02/06/cesiumjs-adds-support-for-indexed-3d-scene-layers-i3s/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/**
* 即使经过大地水准面转换,Cesium World Terrain 高度系统在某些地方仍然与 I3S 数据集高度系统不匹配。
* 设置 ArcGIS Tiled Elevation Terrain 重力相关高度系统以获得更接近的结果。
*/

const viewer = new Cesium.Viewer("cesiumContainer", {
geocoder: false,
sceneModePicker: false,
baseLayerPicker: false,
navigationHelpButton: false,
navigationInstructionsInitiallyVisible: false,
animation: false,
timeline: false,
fullscreenButton: false,
selectionIndicator: false,
skyBox: false,
shouldAnimate: true,
terrain: new Cesium.Terrain(
Cesium.ArcGISTiledElevationTerrainProvider.fromUrl(
"https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer"
)
),
orderIndependentTranslucency: false,
});
viewer.cesiumWidget.creditContainer.style.display = "none";

/**
* 可以在此处添加更多可供浏览的数据集...
*
* 传递给 I3SDataProvider 的 url,支持从 SceneServer
* 加载单个索引 3D 场景(I3S)图层(.<host>/SceneServer/layers/<id>)
* 或场景图层集合(.<host>/SceneServer)。
*/
const tours = {
"Turanga Library":
"https://tiles.arcgis.com/tiles/cFEFS0EWrhfDeVw9/arcgis/rest/services/Turanga_Library/SceneServer",
};

try {
/**
* 创建 i3s 选项以传递用于调试和可视化的可选参数
* 具体参考:https://cesium.com/learn/cesiumjs/ref-doc/I3SDataProvider.html#.ConstructorOptions
*/
const i3sOptions = {
/**
* adjustMaterialAlphaMode属性:根据顶点颜色的透明度调整材质的 alpha 模式的选项。当设置为true时,
* 如果材质未定义 alpha 模式,则对于具有任何透明度的顶点颜色属性的几何体,材质的 alpha 模式将被设置为 BLEND。
*/
adjustMaterialAlphaMode: true,
showFeatures: true, // 确定是否显示要素。为每个要素创建 3D 对象,并允许应用属性过滤器
applySymbology: true, // 确定是否将解析 I3S 符号系统并将其应用于图层。
calculateNormals: true, // 确定是否为没有法线的 I3S 几何体生成平面法线。
};

// 创建一个 I3S data provider
const i3sProvider = await Cesium.I3SDataProvider.fromUrl(
tours["Turanga Library"],
i3sOptions
);

/**
* 添加I3S Building Scene Layer小部件,这个是Cesium封装好的组件。
* 类参考:https://cesium.com/learn/cesiumjs/ref-doc/I3SBuildingSceneLayerExplorer.html?classFilter=I3SBuildingSceneLayerExplorer
*/
Cesium.I3SBuildingSceneLayerExplorer("toolbar", i3sProvider);

// 将 i3s layer provider作为基本数据类型添加
viewer.scene.primitives.add(i3sProvider);

// I3S 加载数据完毕后将相机置于数据范围的中心
const center = Cesium.Rectangle.center(i3sProvider.extent);
center.height = 300.0;
// 通过 I3S BSL(即Building Scene Layer) 范围调整相机高度
let bslLayer = i3sProvider.data;
if (Cesium.defined(bslLayer.layers) && bslLayer.layers.length > 0) {
bslLayer = bslLayer.layers[0];
}
if (
Cesium.defined(bslLayer.fullExtent) &&
Cesium.defined(bslLayer.fullExtent.zmax)
) {
center.height += bslLayer.fullExtent.zmax;
}
const destination = Cesium.Ellipsoid.WGS84.cartographicToCartesian(center);
viewer.camera.setView({
destination: destination,
});

//覆盖主页按钮并将相机置于I3S(数据)范围的中心
viewer.homeButton.viewModel._command = Cesium.createCommand(function () {
viewer.camera.flyTo({
destination: destination,
});
});
} catch (error) {
console.error(`创建 I3S Data Provider时出错: ${error}`);
}

//当前所选要素的相关信息
const selected = {
feature: undefined,
originalColor: new Cesium.Color(),
};

//一个实体对象,它将保存有关当前选定要素的信息,以便在信息框(cesium自带的infobox组件)中显示
const selectedEntity = new Cesium.Entity();
//在InfoBox中展示元数据信息
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
const selectedFeature = selected.feature;

//(鼠标)拾取一个新的要素
const pickedFeature = viewer.scene.pick(movement.position);
if (selectedFeature === pickedFeature) {
return;
}

// 若一个要素先前被选中了, 则取消高亮
if (Cesium.defined(selected.feature)) {
selected.feature.color = selected.originalColor;
selected.feature = undefined;
}

if (
!Cesium.defined(pickedFeature) ||
!Cesium.defined(pickedFeature.content) ||
!Cesium.defined(pickedFeature.content.tile.i3sNode)
) {
viewer.selectedEntity = undefined;
return;
}

// 高亮新选中的要素
selected.feature = pickedFeature;
Cesium.Color.clone(pickedFeature.color, selected.originalColor);
pickedFeature.color = Cesium.Color.BLUE;

const i3sNode = pickedFeature.content.tile.i3sNode;
i3sNode.loadFields().then(function () {
let description = "No attributes";
let name;

const fields = i3sNode.getFieldsForFeature(pickedFeature.featureId);
if (Object.keys(fields).length > 0) {
description = '<table class="cesium-infoBox-defaultTable"><tbody>';
for (const fieldName in fields) {
if (i3sNode.fields.hasOwnProperty(fieldName)) {
description += `<tr><th>${fieldName}</th><td>`;
description += `${fields[fieldName]}</td></tr>`;
if (!Cesium.defined(name) && isNameProperty(fieldName)) {
name = fields[fieldName];
}
}
}
description += `</tbody></table>`;
}
if (!Cesium.defined(name)) {
name = "unknown";
}
selectedEntity.name = name;
selectedEntity.description = description;
viewer.selectedEntity = selectedEntity;
});
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

function isNameProperty(propertyName) {
const name = propertyName.toLowerCase();
if (
name.localeCompare("name") === 0 ||
name.localeCompare("objname") === 0 ||
name.localeCompare("category") === 0
) {
return true;
}
return false;
}