原文链接及内容

实现效果如下图所示:

AEC通常指Architecture, Engineering, and Construction,即建筑、工程和施工。Architectural Design:建筑设计

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<style>
@import url(../templates/bucket.css);

#toolbar .cesium-button {
display: block;
width: 100%;
text-align: left;
}
.cesium-performanceDisplay-defaultContainer {
top: 10px;
}
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>数据加载中...</h1></div>
<div id="toolbar"></div>
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/**
* AEC建筑设计应用案例:一个多层建筑设计的演示,包含场地裁剪、元数据拾取和图层可见性切换。
* Snowdon Towers 示例数据由 Autodesk Revit 提供。
*
* AEC通常指Architecture, Engineering, and Construction,即建筑、工程和施工。
* Architectural Design:建筑设计
*/
const viewer = new Cesium.Viewer("cesiumContainer", {
geocoder: false,
sceneModePicker: false,
homeButton: false,
navigationHelpButton: false,
baseLayerPicker: false,
navigationInstructionsInitiallyVisible: false,
animation: false,
timeline: false,
fullscreenButton: false,
selectionIndicator: false,
skyBox: false,
shouldAnimate: true,
globe: false,
});

viewer.scene.skyAtmosphere.show = true;// 启用渲染天空
viewer.scene.debugShowFramesPerSecond = true;//添加帧速显示
viewer.cesiumWidget.creditContainer.style.display = "none";//隐藏版权信息

// 配置 Ambient Occlusion(环境光遮蔽)
if (Cesium.PostProcessStageLibrary.isAmbientOcclusionSupported(viewer.scene)) {
const ambientOcclusion = viewer.scene.postProcessStages.ambientOcclusion;
ambientOcclusion.enabled = true;
ambientOcclusion.uniforms.intensity = 2.0;
ambientOcclusion.uniforms.bias = 0.1;
ambientOcclusion.uniforms.lengthCap = 0.5;
ambientOcclusion.uniforms.directionCount = 16;
ambientOcclusion.uniforms.stepCount = 32;
}

// 设置为 UTC 时间费城下午 1 点
viewer.clock.currentTime = Cesium.JulianDate.fromIso8601(
"2024-11-22T18:00:00Z"
);

// 设置相机的初始视角
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(-79.886626, 40.021649, 235.65),
orientation: {
heading: 0,
pitch: Cesium.Math.toRadians(-20),
roll: 0,
},
});

// 添加(谷歌地图平台的)Photorealistic(高精度渲染的/逼真的/写实的) 3D tiles数据
let googleTileset;
try {
googleTileset = await Cesium.Cesium3DTileset.fromIonAssetId(2275207);
viewer.scene.primitives.add(googleTileset);
} catch (error) {
console.log(`Error loading tileset: ${error}`);
}

// 添加场地裁剪功能
const positions = Cesium.Cartesian3.fromDegreesArray([
-79.887735, 40.022564, -79.886341, 40.023087, -79.886161, 40.023087,
-79.885493, 40.022032, -79.88703, 40.021456, -79.887735, 40.022564,
]);

/**
* Cesium.ClippingPolygon:允许开发者通过定义闭合的多边形边界,​选择性隐藏或显示三维模型/地图数据的指定区域
*/
const polygon = new Cesium.ClippingPolygon({
positions: positions,
});

const polygons = new Cesium.ClippingPolygonCollection({
polygons: [polygon],
});

googleTileset.clippingPolygons = polygons;

/**
* 该建筑设计所用数据由多个瓦片数据集组成
*/
const tilesetData = [
{ title: "建筑", assetId: 2887123, visible: true },
{ title: "(建筑物)立面", assetId: 2887125, visible: true },
{ title: "(建筑)结构", assetId: 2887130, visible: false },
{ title: "电气设备", assetId: 2887124, visible: true },
{ title: "暖通空调", assetId: 2887126, visible: true },
{ title: "(建筑物的)管路系统", assetId: 2887127, visible: true },
{ title: "场地", assetId: 2887129, visible: true },
];
// 加载每个tileset并创建相应的可见性切换按钮。
for (const { title, assetId, visible } of tilesetData) {
try {
const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(assetId);
viewer.scene.primitives.add(tileset);
tileset.show = visible;

const toggleBtn = Sandcastle.addToggleButton(
title,
visible,
function (checked) {
tileset.show = checked;
}
);
} catch (error) {
console.log(`Error loading tileset (${title}): ${error}`);
}
}

// 获取在左键单击时未拾取要素时的默认左键单击处理程序
const clickHandler = viewer.screenSpaceEventHandler.getInputAction(
Cesium.ScreenSpaceEventType.LEFT_CLICK
);

// 创建将放入信息框中的 HTML,以显示有关当前拾取要素的信息
function createPickedFeatureDescription(pickedFeature) {
let description = `${'<table class="cesium-infoBox-defaultTable"><tbody>'}`;

const propertyIds = pickedFeature.getPropertyIds();

// 按字母顺序对属性进行排序
propertyIds.sort((a, b) => a.localeCompare(b));

const length = propertyIds.length;
for (let i = 0; i < length; ++i) {
const propertyId = propertyIds[i];
const propertyValue = pickedFeature.getProperty(propertyId);

if (Cesium.defined(propertyValue) && propertyValue !== "") {
description += `<tr><th>${propertyId}</th><td>${propertyValue}</td></tr>`;
}
}

description += `</tbody></table>`;

return description;
}

// 一个实体对象,用于保存当前选定特征的信息以便在信息框中显示
const selectedEntity = new Cesium.Entity();

const selected = {
feature: undefined,
originalColor: new Cesium.Color(),
};

const highlighted = {
feature: undefined,
originalColor: new Cesium.Color(),
};

// 悬停时将某个要素颜色变为黄色。
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
if (Cesium.defined(highlighted.feature)) {
highlighted.feature.color = highlighted.originalColor;
highlighted.feature = undefined;
}

const pickedFeature = viewer.scene.pick(movement.endPosition);

if (
!Cesium.defined(pickedFeature) ||
!(pickedFeature instanceof Cesium.Cesium3DTileFeature)
) {
return;
}

if (pickedFeature !== selected.feature) {
highlighted.feature = pickedFeature;
Cesium.Color.clone(pickedFeature.color, highlighted.originalColor);
pickedFeature.color = Cesium.Color.YELLOW;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

// 对选择的要素进行着色并在信息框中显示元数据。
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
if (Cesium.defined(selected.feature)) {
selected.feature.color = selected.originalColor;
selected.feature = undefined;
}

const pickedFeature = viewer.scene.pick(movement.position);
if (
!Cesium.defined(pickedFeature) ||
!(pickedFeature instanceof Cesium.Cesium3DTileFeature)
) {
clickHandler(movement);
return;
}

if (selected.feature === pickedFeature) {
return;
}
selected.feature = pickedFeature;
// 保存所选要素的原始颜色
if (pickedFeature === highlighted.feature) {
Cesium.Color.clone(highlighted.originalColor, selected.originalColor);
highlighted.feature = undefined;
} else {
Cesium.Color.clone(pickedFeature.color, selected.originalColor);
}
pickedFeature.color = Cesium.Color.LIME;

viewer.selectedEntity = selectedEntity;
selectedEntity.description = createPickedFeatureDescription(pickedFeature);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);