🎯 一、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. 动态航线轨迹实现思路与步骤

🧠 实现思路
  1. 定义时间-位置采样点,构建随时间变化的位置属性
  2. 创建航线实体,绑定位置属性与动态方向(随轨迹旋转)
  3. 配置Cesium时钟与时间轴,实现轨迹回放
  4. 优化航线样式(发光、宽度渐变)与交互效果
📝 详细实现步骤
//步骤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转换地形数据
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐