在Cesium中,Cesium3DTile
是与 3D Tiles 数据集中的单个瓦片(tile)相关的类。3D Tiles 是用于展示大规模城市建模、点云数据等 3D 数据的标准格式。而 Cesium3DTile
类正是代表这些数据集中的每一个单独的瓦片。理解这个类对于处理大规模 3D 数据的加载和展示非常重要。
Cesium3DTile
是什么?Cesium3DTile
是一个表示单个 3D Tiles 瓦片的类。在 3D Tiles 中,数据被分割成多个瓦片(tiles),每个瓦片包含一小部分场景的几何数据和其他信息。而 Cesium3DTile
就是一个瓦片对象,它用于描述这些几何体数据如何加载、渲染以及如何在场景中与其他瓦片一起展示。
Cesium3DTile
实际上,开发者不需要直接创建 Cesium3DTile
实例。而是通过 Cesium3DTileset
类动态加载的。你只需要通过 Cesium3DTileset#tileVisible
方法来访问这些瓦片。Cesium3DTile
类中的很多属性和方法是与瓦片的渲染、加载和父子关系相关的。
boundingSphere
(BoundingSphere
):
children
(Array.
):
children
属性,可以访问到一个瓦片的所有子瓦片。computedTransform
(Matrix4
):
content
(Cesium3DTileContent
):
content
会被加载和显示。expireDate
(JulianDate
):
geometricError
(number
):
tileset
(Cesium3DTileset
):
tileset
属性,可以获取到整个 3D Tiles 数据集。parent
(Cesium3DTile
):
transform
(Matrix4
):
getContent()
:
pickFeatures(x, y, level, longitude, latitude)
:
假设我们正在开发一个虚拟城市应用,用户可以在3D地球上查看大城市的建筑物。这些建筑物的数据很庞大,无法一次性加载全部,所以下来的数据是分割成多个瓦片的,每个瓦片包含一部分城市的数据。这里的每个瓦片就是一个 Cesium3DTile
对象。
假设应用已经加载了整个城市的3D Tiles数据集(Cesium3DTileset
),当用户移动到某个区域时,系统会根据视图来加载那些离用户最近的瓦片。每个 Cesium3DTile
就是这些瓦片的一部分,包含了建筑物的几何数据。当瓦片被加载后,它的 content
就会被渲染到屏幕上,而其他瓦片会继续根据需求加载。
// A simple demo of 3D Tiles feature picking with hover and select behavior
// Building data courtesy of NYC OpenData portal: http://www1.nyc.gov/site/doitt/initiatives/3d-building.page
const viewer = new Cesium.Viewer("cesiumContainer", {
terrain: Cesium.Terrain.fromWorldTerrain(),
});
viewer.scene.globe.depthTestAgainstTerrain = true;
// Set the initial camera view to look at Manhattan
const initialPosition = Cesium.Cartesian3.fromDegrees(
-74.01881302800248,
40.69114333714821,
753,
);
const initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(
21.27879878293835,
-21.34390550872461,
0.0716951918898415,
);
viewer.scene.camera.setView({
destination: initialPosition,
orientation: initialOrientation,
endTransform: Cesium.Matrix4.IDENTITY,
});
// Load the NYC buildings tileset
try {
const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(75343);
viewer.scene.primitives.add(tileset);
} catch (error) {
console.log(`Error loading tileset: ${error}`);
}
// HTML overlay for showing feature name on mouseover
const nameOverlay = document.createElement("div");
viewer.container.appendChild(nameOverlay);
nameOverlay.className = "backdrop";
nameOverlay.style.display = "none";
nameOverlay.style.position = "absolute";
nameOverlay.style.bottom = "0";
nameOverlay.style.left = "0";
nameOverlay.style["pointer-events"] = "none";
nameOverlay.style.padding = "4px";
nameOverlay.style.backgroundColor = "black";
// Information about the currently selected feature
const selected = {
feature: undefined,
originalColor: new Cesium.Color(),
};
// An entity object which will hold info about the currently selected feature for infobox display
const selectedEntity = new Cesium.Entity();
// Get default left click handler for when a feature is not picked on left click
const clickHandler = viewer.screenSpaceEventHandler.getInputAction(
Cesium.ScreenSpaceEventType.LEFT_CLICK,
);
// Update the 'nameOverlay' for the given picked feature,
// at the given (screen) position.
function updateNameOverlay(pickedFeature, position) {
if (!Cesium.defined(pickedFeature)) {
nameOverlay.style.display = "none";
return;
}
// A feature was picked, so show its overlay content
nameOverlay.style.display = "block";
nameOverlay.style.bottom = `${viewer.canvas.clientHeight - position.y}px`;
nameOverlay.style.left = `${position.x}px`;
const name = pickedFeature.getProperty("BIN");
nameOverlay.textContent = name;
}
// Create the HTML that will be put into the info box that shows
// information about the currently selected feature
function createPickedFeatureDescription(pickedFeature) {
const description =
`${
'' +
"` +
`` +
`` +
`` +
`` +
`` +
`` +
`BIN "
}${pickedFeature.getProperty("BIN")} DOITT ID ${pickedFeature.getProperty(
"DOITT_ID",
)} SOURCE ID ${pickedFeature.getProperty(
"SOURCE_ID",
)} Longitude ${pickedFeature.getProperty(
"Longitude",
)} Latitude ${pickedFeature.getProperty(
"Latitude",
)} Height ${pickedFeature.getProperty("Height")} Terrain Height (Ellipsoid) ${pickedFeature.getProperty(
"TerrainHeight",
)}
`;
return description;
}
// If silhouettes are supported, silhouette features in blue on mouse over and silhouette green on mouse click.
// If silhouettes are not supported, change the feature color to yellow on mouse over and green on mouse click.
if (Cesium.PostProcessStageLibrary.isSilhouetteSupported(viewer.scene)) {
// Silhouettes are supported
const silhouetteBlue =
Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
silhouetteBlue.uniforms.color = Cesium.Color.BLUE;
silhouetteBlue.uniforms.length = 0.01;
silhouetteBlue.selected = [];
const 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,
]),
);
// Silhouette a feature blue on hover.
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
// If a feature was previously highlighted, undo the highlight
silhouetteBlue.selected = [];
// Pick a new feature
const pickedFeature = viewer.scene.pick(movement.endPosition);
updateNameOverlay(pickedFeature, movement.endPosition);
if (!Cesium.defined(pickedFeature)) {
return;
}
// Highlight the feature if it's not already selected.
if (pickedFeature !== selected.feature) {
silhouetteBlue.selected = [pickedFeature];
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// Silhouette a feature on selection and show metadata in the InfoBox.
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
// If a feature was previously selected, undo the highlight
silhouetteGreen.selected = [];
// Pick a new feature
const pickedFeature = viewer.scene.pick(movement.position);
if (!Cesium.defined(pickedFeature)) {
clickHandler(movement);
return;
}
// Select the feature if it's not already selected
if (silhouetteGreen.selected[0] === pickedFeature) {
return;
}
// Save the selected feature's original color
const highlightedFeature = silhouetteBlue.selected[0];
if (pickedFeature === highlightedFeature) {
silhouetteBlue.selected = [];
}
// Highlight newly selected feature
silhouetteGreen.selected = [pickedFeature];
// Set feature infobox description
viewer.selectedEntity = selectedEntity;
selectedEntity.description = createPickedFeatureDescription(pickedFeature);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
} else {
// Silhouettes are not supported. Instead, change the feature color.
// Information about the currently highlighted feature
const highlighted = {
feature: undefined,
originalColor: new Cesium.Color(),
};
// Color a feature yellow on hover.
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
// If a feature was previously highlighted, undo the highlight
if (Cesium.defined(highlighted.feature)) {
highlighted.feature.color = highlighted.originalColor;
highlighted.feature = undefined;
}
// Pick a new feature
const pickedFeature = viewer.scene.pick(movement.endPosition);
updateNameOverlay(pickedFeature, movement.endPosition);
if (!Cesium.defined(pickedFeature)) {
return;
}
// Highlight the feature if it's not already selected.
if (pickedFeature !== selected.feature) {
highlighted.feature = pickedFeature;
Cesium.Color.clone(pickedFeature.color, highlighted.originalColor);
pickedFeature.color = Cesium.Color.YELLOW;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// Color a feature on selection and show metadata in the InfoBox.
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
// If a feature was previously selected, undo the highlight
if (Cesium.defined(selected.feature)) {
selected.feature.color = selected.originalColor;
selected.feature = undefined;
}
// Pick a new feature
const pickedFeature = viewer.scene.pick(movement.position);
if (!Cesium.defined(pickedFeature)) {
clickHandler(movement);
return;
}
// Select the feature if it's not already selected
if (selected.feature === pickedFeature) {
return;
}
selected.feature = pickedFeature;
// Save the selected feature's original color
if (pickedFeature === highlighted.feature) {
Cesium.Color.clone(highlighted.originalColor, selected.originalColor);
highlighted.feature = undefined;
} else {
Cesium.Color.clone(pickedFeature.color, selected.originalColor);
}
// Highlight newly selected feature
pickedFeature.color = Cesium.Color.LIME;
// Set feature infobox description
viewer.selectedEntity = selectedEntity;
selectedEntity.description = createPickedFeatureDescription(pickedFeature);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}