在本教程中,您将学习如何创建一个 Cesium 应用程序以用您自己的 3D 模型替换真实城市中的建筑物。
您可以使用它来可视化拟建建筑物的影响。它如何改变天际线?从特定楼层或房间看去会是什么样子?
我们将介绍如何:
- 在网络上设置和部署您的 Cesium 应用程序
- 添加全球 3D 建筑、地形和图像的基础图层
- 隐藏单个建筑物并用您自己的 3D 模型替换它们
这是您将构建的应用程序。您可以切换建议的建筑物并从多个角度查看它。
开始之前
我们将从 Cesium ion 获取全球卫星图像、3D 建筑和地形,Cesium ion 是一个用于流式传输和托管 3D 内容的开放平台。 如果您还没有免费的 Cesium ion 帐户,请注册一个。
登录后:
- 转到您的 Access Tokens 选项卡。
- 请注意默认令牌旁边的复制按钮。我们将在下一步中使用此令牌。
Cesiumion 是一个用于流式传输和托管 3D 内容的开放平台,包括全球精选数据,您可以使用这些数据创建自己的真实世界应用程序。
步骤1:设置你的Cesium 应用
我们将使用开源 JavaScript 引擎 CesiumJS 创建我们的应用程序。我们将使用在线 IDE Glitch 来托管我们的应用程序。
- 使用我们放在一起的基本模板创建一个新的 Glitch 项目。
- 单击左侧面板中的 index.html 查看应用程序代码。
- 替换为您的令牌页面
your_token_here
中的访问令牌 。 - 通过单击顶部的 Show 并选择 Next to The Code 来运行应用程序。
到目前为止,index.html 中的代码做了三件事:
- 导入 CesiumJS 库。JavaScript和 CSS 文件在这两行中加载:
<script src="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Cesium.js"></script>
<link
href="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"
/>
- 为场景添加一个 HTML 容器:
<div id=cesiumContainer></div>
。 - 初始化查看器:
const viewer = new Cesium.Viewer('cesiumContainer');
。
你现在有一个基本的 CesiumJS 应用程序在你的浏览器中运行,其中包含来自 Cesium ion 的全球卫星图像。
配置自动刷新
每次代码更改时,Glitch 都会自动刷新页面。您可以通过单击左上角的项目名称并取消选中此框来切换它:
使用应用程序窗口顶部的刷新按钮重新运行应用程序:
步骤 2:添加 Cesium OSM 建筑和 Cesium 世界地形
Cesium OSM Buildings 是一个全球基础层,拥有超过 3.5 亿个来自 OpenStreetMap 数据的建筑物。它用作 3D Tiles,这是 Cesium 创建的开放标准,可以将 3D 内容流式传输到任何兼容的客户端。
让我们添加这些图层,然后将相机移动到我们虚构的新建筑所在的城市 — 科罗拉多州丹佛市。
- 用下面的代码替换 index.html 中的 JavaScript 代码,保留之前的访问令牌行。
- 单击并拖动以移动相机。拖动时按住 CTRL 以倾斜。
- 单击任何建筑物以查看其元数据。
// Keep your Cesium.Ion.defaultAccessToken = 'your_token_here' line above.
// STEP 2 CODE
// Initialize the viewer with Cesium World Terrain.
const viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain()
});
// Add Cesium OSM Buildings.
const buildingsTileset = viewer.scene.primitives.add(Cesium.createOsmBuildings());
// Fly the camera to Denver, Colorado at the given longitude, latitude, and height.
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(-104.9965, 39.74248, 4000)
});
此时,您完整的 index.html 将如下所示(访问令牌除外)。在以后的步骤中,您将在标记内的现有代码下方添加新代码 script。
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<link href="style.css" rel="stylesheet">
</head>
<body>
<div id="cesiumContainer"></div>
<script>
// Your access token can be found at: https://cesium.com/ion/tokens.
// This is the default access token from your ion account
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3ODdlN2I5OS1iZDMyLTQ2MTItODQwYi01MGE3NGI3NGIzNGUiLCJpZCI6MTE4MjU5LCJpYXQiOjE2NzA5ODI0MDd9.XpfuSxbcNuxNF1jMqI5FxveHXhiq6VVCsww80hIVAME';
// Keep your Cesium.Ion.defaultAccessToken = 'your_token_here' line above.
// STEP 2 CODE
// Initialize the viewer with Cesium World Terrain.
const viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain()
});
// Add Cesium OSM Buildings.
const buildingsTileset = viewer.scene.primitives.add(Cesium.createOsmBuildings());
// Fly the camera to Denver, Colorado at the given longitude, latitude, and height.
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(-104.9965, 39.74248, 4000)
});
</script>
</body>
</html>
Cesium OSM Buildings 与全球高分辨率 3D 地形图层 Cesium World Terrain 绑定。这使其非常适合需要精确建筑高度的应用,例如洪水分析工具。
步骤 3:确定新建建筑面积
在我们添加新建筑物之前,让我们添加一个 GeoJSON 文件来标记它的足迹。这将告诉我们哪些现有建筑物需要拆除。
- 下载 GeoJSON 文件。
- 将 GeoJSON 文件拖放到您的 Cesium ion 仪表板中。
- 按 上传 。
步骤 4:上传后,记下预览窗口下的资产 ID。
- 在 index.html 中添加以下代码。
- 替换
your_asset_id
为您的资产 ID。ID 是一个数字,因此您不需要引号。
// STEP 3 CODE
async function addBuildingGeoJSON() {
// Load theGeoJSONfile from Cesium ion.
const geoJSONURL = await Cesium.IonResource.fromAssetId(your_asset_id);
// Create the geometry from the GeoJSON, and clamp it to the ground.
constGeoJSON= await Cesium.GeoJsonDataSource.load(geoJSONURL, { clampToGround: true });
// Add it to the scene.
const dataSource = await viewer.dataSources.add(geoJSON);
// By default, polygons in CesiumJS will be draped over all3Dcontent in the scene.
// Modify the polygons so that this draping only applies to the terrain, not3Dbuildings.
for (const entity of dataSource.entities.values) {
entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;
}
// Move the camera so that the polygon is in view.
viewer.flyTo(dataSource);
}
addBuildingGeoJSON();
您现在会在地面上看到建筑物的足迹。使用鼠标滚轮放大或右键单击并拖动以仔细查看。
步骤 5:隐藏现场现有的 3D 建筑
现在我们已经确定了新建筑的去向,我们可以看到当前有哪些建筑。我们将使用 3D Tiles Styling Language 来隐藏它们。
在上面的占地面积中,我们可以看到在我们拟建的新建筑所在地有六座建筑——一座大型建筑和五座小得多的建筑。
- 添加以下代码。它隐藏了所有较小的 3D 建筑。
// STEP 4 CODE
// Hide individual buildings in this area using3DTiles Styling language.
buildingsTileset.style = new Cesium.Cesium3DTileStyle({
// Create a style rule to control each building's "show" property.
show: {
conditions : [
// Any building that has this elementId will have `show = false`.
['${elementId} === 332469316', false],
['${elementId} === 332469317', false],
['${elementId} === 235368665', false],
['${elementId} === 530288180', false],
['${elementId} === 530288179', false],
// If a building does not have one of these elementIds, set `show = true`.
[true, true]
]
},
// Set the default color style for this particular3DTileset.
// For any building that has a `cesium#color` property, use that color, otherwise make it white.
color: "Boolean(${feature['cesium#color']}) ? color(${feature['cesium#color']}) : color('#ffffff')"
});
- 扩展此代码以隐藏剩余的 3D 建筑。
- 单击建筑物以找到其
elementI
。 - 添加另一行,如:
['${elementId} === large_building_elementId', false]
步骤 6:上传并定位新建筑
让我们上传建议的建筑模型。
- 下载此 glTF 模型。
- 将其拖放到您的 Cesium 离子仪表板中。
- 选择 3D Model (tile as 3D Tiles) 并按上传 。
- 完成拼贴后,单击 资产预览窗口顶部的 Adjust Tileset Location 按钮。
- 在搜索框中输入建筑物地址 1250 Cherokee Street ,然后单击 下一步 。
- 使用查看器上的控件,在视觉上定位和旋转建筑物,使其与下面的卫星图像对齐。您的最终设置应大致为:
经度:-104.9909
纬度:39.73579
身高:1577
航向:-8
- 按 保存。
确保地理定位准确性
在本教程中,您手动定位了一座新建筑。如果建筑物已经进行了地理参考,Cesium ion 会自动将其放置在正确的位置。您还可以使用 REST API 对其进行地理定位。通过地理定位指南了解更多信息 。
步骤 7:将新建筑添加到场景中
现在让我们将新建筑物添加到场景中。
- 在资产预览窗口下获取我们刚刚地理定位的建筑模型的资产 ID。
- 在 index.html 中添加以下代码。
- 替换
your_asset_id
为您的资产 ID。
// STEP 6 CODE
// Add the3DTileset you created from your Cesium ion account.
const newBuildingTileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: Cesium.IonResource.fromAssetId(your_asset_id)
})
);
// Move the camera to the new building.
viewer.flyTo(newBuildingTileset);
步骤 8:添加一个按钮来切换新建筑
- 在 index.html 中,将按钮添加到您的
<body>
标签内的上方<script
。
<button id="toggle-building">Toggle new building</button>
- 在 head 标签内添加以下 CSS
style
标签:
<style type="text/css">
#toggle-building { z-index: 1; position: fixed; top: 5px; left: 5px; }
</style>
- 在 index.html 中添加以下 JavaScript:
// STEP 7 CODE
// Toggle the tileset's show property when the button is clicked.
document.querySelector('#toggle-building').onclick = function() {
newBuildingTileset.show = !newBuildingTileset.show;
};
步骤 9:考虑建筑对周围环境的影响
现在您可以比较有和没有这座新建筑的场景!
丹佛的全景山景备受推崇。这座建筑如何影响其他地方的景色,例如科罗拉多州议会大厦?
对科罗拉多州议会大厦景观的影响。
要重现这一点,请搜索美国科罗拉多州丹佛市的州议会大厦并调整相机。
我们甚至可以探索国会大厦入口处的景色将如何变化。
从更接近地面的角度对视图的影响。
完整教程源码
这是带有 your_token_here
和 your_asset_id
占位符的此应用程序的完整源代码。
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<link href="style.css" rel="stylesheet">
<style type="text/css">
#toggle-building { z-index: 1; position: fixed; top: 5px; left: 5px; }
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<button id="toggle-building">Toggle new building</button>
<script>
// Your access token can be found at: https://cesium.com/ion/tokens.
// This is the default access token from your ion account
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3ODdlN2I5OS1iZDMyLTQ2MTItODQwYi01MGE3NGI3NGIzNGUiLCJpZCI6MTE4MjU5LCJpYXQiOjE2NzA5ODI0MDd9.XpfuSxbcNuxNF1jMqI5FxveHXhiq6VVCsww80hIVAME';
// Keep your Cesium.Ion.defaultAccessToken = 'your_token_here' line from above.
// STEP 2 CODE
// Initialize the viewer with Cesium World Terrain.
const viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain()
});
// Add Cesium OSM Buildings.
const buildingsTileset = viewer.scene.primitives.add(Cesium.createOsmBuildings());
// Fly the camera to Denver, Colorado at the given longitude, latitude, and height.
/* viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(-104.9965, 39.74248, 4000)
}); */
// STEP 3 CODE
async function addBuildingGeoJSON() {
// Load theGeoJSONfile from Cesium ion.
const geoJSONURL = await Cesium.IonResource.fromAssetId(your_asset_id);
// Create the geometry from the GeoJSON, and clamp it to the ground.
constGeoJSON= await Cesium.GeoJsonDataSource.load(geoJSONURL, { clampToGround: true });
// Add it to the scene.
const dataSource = await viewer.dataSources.add(geoJSON);
// By default, polygons in CesiumJS will be draped over all3Dcontent in the scene.
// Modify the polygons so that this draping only applies to the terrain, not3Dbuildings.
for (const entity of dataSource.entities.values) {
entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;
}
// Move the camera so that the polygon is in view.
// viewer.flyTo(dataSource);
}
addBuildingGeoJSON();
// STEP 4 CODE
// Hide individual buildings in this area using3DTiles Styling language.
buildingsTileset.style = new Cesium.Cesium3DTileStyle({
// Create a style rule to control each building's "show" property.
show: {
conditions : [
// Any building that has this elementId will have `show = false`.
['${elementId} === 532245203', false],
['${elementId} === 332469316', false],
['${elementId} === 332469317', false],
['${elementId} === 235368665', false],
['${elementId} === 530288180', false],
['${elementId} === 530288179', false],
// If a building does not have one of these elementIds, set `show = true`.
[true, true]
]
},
// Set the default color style for this particular3DTileset.
// For any building that has a `cesium#color` property, use that color, otherwise make it white.
color: "Boolean(${feature['cesium#color']}) ? color(${feature['cesium#color']}) : color('#ffffff')"
});
// STEP 6 CODE
// Add the3DTileset you created from your Cesium ion account.
const newBuildingTileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: Cesium.IonResource.fromAssetId(your_asset_id)
})
);
// Move the camera to the new building.
viewer.flyTo(newBuildingTileset);
// STEP 7 CODE
// Toggle the tileset's show property when the button is clicked.
document.querySelector('#toggle-building').onclick = function() {
newBuildingTileset.show = !newBuildingTileset.show;
};
</script>
</body>
</html>
下一步
如果您有自己的建筑模型,请尝试使用它而不是提供的示例 —— glTF、OBJ 和 FBX 都受支持。或者将建筑物放置在您自己的城市中。
请参阅 3D 模型导入指南以了解更多信息。
评论 (0)