Cesium中的 Entity、Terrain、DataSource开发场景示例
是 Cesium 中用于描述随时间变化的三维位置属性的核心类,支持通过采样点插值生成平滑的动态轨迹。它通过存储多个时间戳对应的笛卡尔坐标,自动在时间区间内进行插值计算,实现位置的连续变化。
·
🎯 一、Entity模块:SampledPositionProperty 深度解析与动态航线实现
1. SampledPositionProperty 核心定义与用途
🔍 定义
SampledPositionProperty 是 Cesium 中用于描述随时间变化的三维位置属性的核心类,支持通过采样点插值生成平滑的动态轨迹。它通过存储多个时间戳对应的笛卡尔坐标,自动在时间区间内进行插值计算,实现位置的连续变化。
🎯 核心用途
- 无人机/船舶等移动目标的动态轨迹可视化
- 卫星轨道、导弹飞行路径的时空数据回放
- 基于时间序列的地理数据动画展示
- 支持线性、拉格朗日、埃尔米特等多种插值算法,满足不同平滑度需求
2. SampledPositionProperty 使用方式
基础API
| 方法/属性 | 功能 | 示例 |
|---|---|---|
new Cesium.SampledPositionProperty() |
创建空的位置属性 | const position = new Cesium.SampledPositionProperty(); |
addSample(time, position) |
添加时间-位置采样点 | position.addSample(Cesium.JulianDate.fromDate(new Date('2024-01-01T00:00:00Z')), Cesium.Cartesian3.fromDegrees(116.4, 39.9)); |
setInterpolationOptions(options) |
设置插值算法 | position.setInterpolationOptions({ interpolationDegree: 3, interpolationAlgorithm: Cesium.HermitePolynomialApproximation }); |
getValue(time) |
获取指定时间的位置 | const currentPos = position.getValue(Cesium.JulianDate.now()); |
代码示例:创建带插值的动态位置属性
// 初始化位置属性,使用埃尔米特插值(平滑带速度)
const position = new Cesium.SampledPositionProperty();
position.setInterpolationOptions({
interpolationDegree: 3,
interpolationAlgorithm: Cesium.HermitePolynomialApproximation
});
// 添加采样点(时间+位置)
const startTime = Cesium.JulianDate.fromDate(new Date('2024-01-01T00:00:00Z'));
position.addSample(startTime, Cesium.Cartesian3.fromDegrees(116.4, 39.9, 1000));
position.addSample(Cesium.JulianDate.addSeconds(startTime, 30, new Cesium.JulianDate()), Cesium.Cartesian3.fromDegrees(116.5, 39.95, 1500));
position.addSample(Cesium.JulianDate.addSeconds(startTime, 60, new Cesium.JulianDate()), Cesium.Cartesian3.fromDegrees(116.6, 40.0, 2000));
3. 动态航线轨迹实现思路与步骤
🧠 实现思路
- 定义时间-位置采样点,构建随时间变化的位置属性
- 创建航线实体,绑定位置属性与动态方向(随轨迹旋转)
- 配置Cesium时钟与时间轴,实现轨迹回放
- 优化航线样式(发光、宽度渐变)与交互效果
📝 详细实现步骤
//步骤1:初始化时间
const startTime = Cesium.JulianDate.fromDate(new Date(2015, 2, 25, 16));
const endTime = Cesium.JulianDate.addSeconds(startTime, 360, new Cesium.JulianDate());
viewer.clock.startTime = startTime.clone();
viewer.clock.stopTime = endTime.clone();
viewer.clock.currentTime = startTime.clone();
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; // 循环播放
viewer.clock.multiplier = 10; // 10倍速播放
// 将时间线设置为模拟范围
viewer.timeline.zoomTo(startTime, endTime);
// 步骤2:创建SampledPositionProperty与采样点
const positionProperty = new Cesium.SampledPositionProperty();
positionProperty.setInterpolationOptions({
interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
interpolationDegree: 3
});
// 添加北京→天津→唐山的轨迹点
positionProperty.addSample(startTime, Cesium.Cartesian3.fromDegrees(116.4, 39.9, 1000));
positionProperty.addSample(Cesium.JulianDate.addSeconds(startTime, 20, new Cesium.JulianDate()), Cesium.Cartesian3.fromDegrees(117.2, 39.1, 1500));
positionProperty.addSample(endTime, Cesium.Cartesian3.fromDegrees(118.1, 39.6, 2000));
// 步骤3:创建动态航线实体
const routeEntity = viewer.entities.add({
// 将实体可见性设置为与模拟时间相同的间隔
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: startTime,
stop: endTime,
}),
]),
// 绑定动态位置属性
position: positionProperty,
// 飞机模型:随轨迹自动旋转方向
model: {
uri: './model/Cesium_Air.glb',
scale: 20,
minimumPixelSize: 64
},
// 自动计算模型朝向(沿轨迹前进方向)
orientation: new Cesium.VelocityOrientationProperty(positionProperty),
// 航线样式
path: {
resolution: 1,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.1,
color: Cesium.Color.YELLOW,
}),
width: 10,
},
});
// // 步骤4:添加轨迹点标记(可选)
// const pointEntity = viewer.entities.add({
// position: positionProperty,
// billboard: {
// image: './texture/gzt.png',
// scale: 0.5,
// color: Cesium.Color.RED
// }
// });
// 步骤5:缩放到航线范围
viewer.zoomTo(routeEntity);
⚠️ 注意事项
- 采样点时间间隔不宜过大,否则插值会出现明显跳跃
- 大量采样点建议使用
SampledPositionProperty.fromArray()批量创建 - 若需要轨迹回放循环,设置
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP
📊 二、DataSource模块:常见开发场景与使用注意事项
1. 核心开发场景
🎯 场景1:批量加载静态地理数据(如行政区划、POI)
- 适用场景:加载GeoJSON/TopoJSON格式的行政区划、兴趣点数据
- 示例代码:
Cesium.GeoJsonDataSource.load('https://raw.githubusercontent.com/cesiumjs/cesium/master/Apps/SampleData/ne_10m_us_states.topojson')
.then(dataSource => {
viewer.dataSources.add(dataSource);
// 批量设置样式
dataSource.entities.values.forEach(entity => {
entity.polygon.material = Cesium.Color.fromRandom({ alpha: 0.6 });
entity.polygon.outlineColor = Cesium.Color.WHITE;
});
})
.catch(error => console.error('加载失败:', error));
🎯 场景2:实时动态数据更新(如船舶、无人机轨迹)
- 适用场景:通过CZML格式实现实时位置更新,支持增量数据推送
- 示例代码:
// 初始化CZML数据源
const czmlDataSource = new Cesium.CzmlDataSource();
viewer.dataSources.add(czmlDataSource);
// 模拟实时推送数据(每2秒更新一次位置)
setInterval(() => {
const now = Cesium.JulianDate.now();
const lon = 116.4 + Math.random() * 0.1;
const lat = 39.9 + Math.random() * 0.1;
// 增量添加CZML数据
czmlDataSource.process([{
id: 'drone',
position: {
epoch: now.toIso8601(),
cartesian: [0, Cesium.Cartesian3.toArray(Cesium.Cartesian3.fromDegrees(lon, lat, 500))]
}
}]);
}, 2000);
🎯 场景3:时空数据可视化(如历史台风路径、卫星轨道)
- 适用场景:加载带时间戳的时空数据,通过时间轴回放历史轨迹
- 核心优势:自动处理时间序列数据,无需手动管理SampledPositionProperty
2. 使用注意事项
⚠️ 异步加载处理
- DataSource加载为异步操作,必须通过
then()或async/await处理,避免未加载完成就操作实体 - 必须添加错误捕获,处理网络异常或数据格式错误
⚠️ 坐标系与数据格式
- GeoJSON默认使用WGS84(EPSG:4326)坐标系,无需转换;若使用其他坐标系,需通过
Cesium.Transforms转换 - CZML支持动态数据更新,但需确保数据格式符合Cesium规范(参考CZML官方文档)
⚠️ 性能优化
- 大数据量(>10000实体)建议使用
Cesium.CzmlDataSource的增量加载,避免一次性加载所有数据 - 静态数据加载后,可通过
dataSource.entities.suspendEvents()暂停事件监听,提升渲染性能 - 不再使用的DataSource需调用
dataSource.destroy()释放内存
⚠️ 样式批量设置
- 优先通过
dataSource.entities.values批量设置样式,避免循环调用viewer.entities.add() - 支持通过
dataSource.clampToGround统一设置所有实体贴地渲染
🌍 三、Terrain模块:地形渲染深度解析与实战示例
1. 核心使用场景
🎯 场景1:城市三维建模与规划
- 适用场景:加载高精度倾斜摄影地形,实现城市建筑与地形的融合展示
- 核心要求:支持Quantized Mesh、STK Terrain等格式,地形精度≥1m
🎯 场景2:低空飞行模拟与航线规划
- 适用场景:加载地形数据实现通视分析、地形碰撞检测,确保飞行安全
- 核心要求:支持地形夸张、通视分析API
🎯 场景3:自然资源与环境监测
- 适用场景:加载DEM地形数据,实现地形起伏、坡度坡向分析
- 核心要求:支持GeoTIFF、DTED等DEM格式
2. 核心API与实战示例
🎯 示例1:加载Cesium Ion全球地形
const viewer = new Cesium.Viewer('cesiumContainer', {
// 加载Cesium Ion全球地形(需配置Ion Token)
terrainProvider: Cesium.createWorldTerrain({
requestVertexNormals: true, // 启用法线,支持光照效果
requestWaterMask: true // 启用水面mask,实现真实水面渲染
})
});
// 调整地形夸张(默认1,值越大地形起伏越明显)
viewer.scene.globe.terrainExaggeration = 2.0;
// 启用大气散射效果
viewer.scene.globe.showGroundAtmosphere = true;
🎯 示例2:加载本地Quantized Mesh地形
const terrainProvider = new Cesium.CesiumTerrainProvider({
url: '/terrain', // 本地地形服务地址(需部署Quantized Mesh格式地形)
requestVertexNormals: true,
requestWaterMask: false
});
viewer.scene.terrainProvider = terrainProvider;
// 缩放到地形范围
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 5000),
orientation: { pitch: Cesium.Math.toRadians(-60) }
});
🎯 示例3:地形通视分析(判断两点间是否可见)
// 定义通视分析起点与终点
const startPosition = Cesium.Cartesian3.fromDegrees(116.4, 39.9, 1000);
const endPosition = Cesium.Cartesian3.fromDegrees(116.5, 39.95, 1000);
// 执行通视分析
const visibility = viewer.scene.globe.computeVisibilityBetweenPoints(startPosition, endPosition);
console.log(`两点间是否可见:${visibility.visible}`);
// 绘制通视线与遮挡点
viewer.entities.add({
polyline: {
positions: [startPosition, endPosition],
width: 2,
material: visibility.visible ? Cesium.Color.GREEN : Cesium.Color.RED
}
});
// 绘制遮挡点(若存在)
if (!visibility.visible) {
viewer.entities.add({
position: visibility.occlusionPoint,
billboard: { image: 'https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Widgets/Images/pin.png', color: Cesium.Color.RED }
});
}
🎯 示例4:地形与影像对齐优化
- 当地形与影像出现偏移时,通过调整地形偏移量修正:
viewer.scene.globe.terrainOffset = new Cesium.Cartesian3(0, 0, 10); // Z轴偏移10米
3. 注意事项
⚠️ 地形格式支持
- Cesium优先推荐Quantized Mesh格式,性能最优;支持DEM(GeoTIFF、DTED)、STK Terrain等格式
- 本地地形需部署为HTTP服务,支持CORS跨域
⚠️ 性能优化
- 大规模地形建议使用地形金字塔,根据相机高度自动加载不同精度的地形瓦片
- 关闭不必要的地形属性(如
requestWaterMask)可提升加载速度
⚠️ 坐标系一致性
- 地形数据必须与影像数据坐标系一致(默认WGS84),否则会出现偏移
- 若使用自定义坐标系,需通过
Cesium.Transforms转换地形数据
更多推荐



所有评论(0)