原文地址:Hide Regions of 3D Tiles or Terrain with Clipping Polygons – Cesium
裁剪多边形(ClippingPolygons)能够有针对性地将 3D 瓦片集或地形的特定区域进行隐藏。当需要在全球数据集中隔离感兴趣的区域,或者在现有数据集中添加重叠的设计模型时,该功能非常实用。
在本教程中,我们会在 Google Photorealistic 3D 瓦片中添加一个拟建的道路设计模型,为用户提供项目所需的额外地理空间背景。
在本指南中,您将学会如何:
- 在 Google Photorealistic 3D 瓦片中嵌入设计好的模型
- 使用反向裁剪区域隔离一个区域
前提条件
- 一个基础的 CesiumJS 应用程序。请参阅 CesiumJS 快速入门 - 掘金 (juejin.cn) 以构建基础的 CesiumJS 应用程序。为获得最佳效果,请确保您的应用程序版本为 CesiumJS 1.117 或更高版本。
- 一个 Cesium ion 账户和令牌
第一步:加载 Google Photorealistic 3D 瓦片
首先,构建一个 Cesium Viewer 并添加来自 Cesium ion 的 Google Photorealistic 3D 瓦片数据集。
详细的教程请参考 使用 CesiumJS 加载 Google Maps Platform 的 Photorealistic 3D Tiles - 掘金 (juejin.cn)。
const viewer = new Cesium.Viewer("cesiumContainer", {
timeline: false,
animation: false,
sceneModePicker: false,
baseLayerPicker: false,
globe: false,
});
// 为感兴趣的区域设置最佳照明
viewer.scene.skyAtmosphere.show = true;
const currentTime = Cesium.JulianDate.fromIso8601(
"2020-01-09T23:00:39.018261982600961346Z"
);
viewer.clock.currentTime = currentTime;
// 添加真实感3D瓦片
let globalTileset;
try {
globalTileset = await Cesium.createGooglePhotorealistic3DTileset();
viewer.scene.primitives.add(globalTileset);
} catch (error) {
console.log(`加载真实感3D瓦片集时出错。
${error}`);
}
第二步:定义设计模型的轮廓
接下来,我们要定义从 3D 瓦片集中裁剪出的区域,以便将其替换为我们的设计模型。为此,我们需要一个位置列表,这些位置将从托管在 Cesium ion 上的 GeoJSON 文件中获取。
外部应用程序通常会界定一个轮廓或大纲。在此,我们将使用托管的 GeoJSON 文件加载位置列表,以便于进行操作。不过,您也可以使用其他数据源,例如 KML 或 CZML,或者如步骤 3 所述,手动定义位置列表。
我们还将利用这些位置定义的多边形来设置相机指向相关位置。
添加以下代码:
// 加载一个包含项目轮廓位置的GeoJSON文件
let footprint;
try {
const resource = await Cesium.IonResource.fromAssetId(2533131);
const dataSource = await Cesium.GeoJsonDataSource.load(resource, {
clampToGround: true,
});
viewer.dataSources.add(dataSource);
footprint = dataSource.entities.values.find((entity) =>
Cesium.defined(entity.polygon)
);
footprint.polygon.outline = false;
// 缩放到数据位置,并设置默认视图
const cameraOffset = new Cesium.HeadingPitchRange(
Cesium.Math.toRadians(95.0),
Cesium.Math.toRadians(-18.0),
600.0
);
viewer.zoomTo(footprint, cameraOffset);
viewer.homeButton.viewModel.command.beforeExecute.addEventListener(
(e) => {
e.cancel = true;
viewer.zoomTo(footprint, cameraOffset);
}
);
} catch (error) {
console.log(`加载GeoJSON时出错。${error}`);
}
第三步:使用轮廓定义裁剪多边形
现在,我们可以确定我们的位置了。接下来,让我们提取这些位置,并利用它们来定义裁剪多边形。
添加以下代码:
// 隐藏轮廓
footprint.show = false;
// 基于加载的轮廓多边形添加裁剪多边形
const positions = footprint.polygon.hierarchy.getValue().positions;
const clippingPolygons = new Cesium.ClippingPolygonCollection({
polygons: [
new Cesium.ClippingPolygon({
positions: positions,
}),
],
});
// 将裁剪多边形集合添加到全局瓦片集
globalTileset.clippingPolygons = clippingPolygons;
裁剪多边形也可以通过手动定义位置列表来实现。例如:
new Cesium.ClippingPolygon({
positions: Cesium.Cartesian3.fromDegreesArray(
[
-105.0077102972673, 39.75198671798765,
-105.0095858062031, 39.75049417970743,
-105.00969000114443, 39.75035082687128,
-105.00972838875393, 39.75013579705808,
-105.00971742086537, 39.74997136204101,
-105.00962967775735, 39.749768979944236,
-105.00932806082336, 39.74928832007956,
]
),
}),
第四步:加载设计模型
最后,我们要从 Cesium ion 上加载一个最终设计模型的 3D Tiles,以填充我们在上一步中裁剪出的区域。
// 添加拟建新道路的瓦片集
let buildingTileset;
try {
buildingTileset = await Cesium.Cesium3DTileset.fromIonAssetId(2533124);
viewer.scene.primitives.add(buildingTileset);
} catch (error) {
console.log(`加载建筑瓦片集时出错。
${error}`);
}
第五步:使用反向裁剪
有时候,在运行时将单个区域进行隔离是非常有用的。例如,若要突出展示设计中的区域,我们可以对裁剪区域进行反转。
添加以下代码:
// 隐藏设计瓦片集
buildingTileset.show = false;
// 反转裁剪区域
clippingPolygons.inverse = true;
下一步
完整的 Sandcastle 示例可参考 AEC裁剪,其中涵盖了上述每个步骤的相关代码。
此外,请查看 裁剪区域Sandcastle示例,了解如何动态添加或移除裁剪多边形,以及如何将它们应用于地形数据集。