You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cesium:如何在Primitive上同时实现贴地与地形深度检测?

解决Cesium中Primitive箭头在depthTestAgainstTerrain开启时clampToGround失效的问题

问题描述

我需要绘制大量箭头,Cesium中只能通过Primitive实现箭头绘制。但开启depthTestAgainstTerrain = true后,即使设置了clampToGround: true,箭头仍会在地面上方消失。

原实现代码:

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;
scene.globe.depthTestAgainstTerrain = true;
// Create sample polyline primitive.
var polylines = scene.primitives.add(new Cesium.PolylineCollection());

var centerLon = -42.25;
var centerLat = -22.25;
var angle = 47;
var distance = 50000;
var nPos = project( centerLat, centerLon, distance, angle );

console.log( JSON.stringify( nPos ) );

var polyline = polylines.add({
    positions : Cesium.Cartesian3.fromDegreesArray([centerLon, centerLat, nPos.lon, nPos.lat]),
    material: Cesium.Material.fromType('PolylineArrow', {
      color: new Cesium.Color.fromBytes(255, 255, 0, 185)
    }),  
    width : 15.0,
    clampToGround : true
});

function project( lat, lon, distance, angle ){
  var radian = Cesium.Math.toRadians(angle);
  var ellipsoid = Cesium.Ellipsoid.WGS84;
  var firstPos = Cesium.Cartesian3.fromDegrees(lon,lat, 0);
  var ENU = Cesium.Transforms.eastNorthUpToFixedFrame(firstPos, ellipsoid);
  var offsetX = distance * Math.sin(radian);
  var offsetY = distance * Math.cos(radian);
  var offset = new Cesium.Cartesian3(offsetX, offsetY, 0);
  var thePosition = Cesium.Matrix4.multiplyByPoint(ENU, offset, new Cesium.Cartesian3());
  const cartographic = Cesium.Cartographic.fromCartesian( thePosition );
  const longitude = Cesium.Math.toDegrees(cartographic.longitude);
  const latitude = Cesium.Math.toDegrees(cartographic.latitude);  
  return { lat: latitude, lon: longitude }; 
} 

问题原因

当开启depthTestAgainstTerrain时,Cesium会对比Primitive的深度和地形的深度。而PolylineCollection的clampToGround只是将线贴在椭球表面,而非真实地形表面。如果真实地形比椭球高,箭头就会被地形的深度测试遮挡,看起来像是在地面上方消失。

解决步骤

  1. 获取真实地形高度:使用Cesium的sampleTerrainMostDetailed API获取每个点的实际地形高度,替换原来的0高度。
  2. 异步处理地形数据:地形采样是异步操作,需在获取到高度后再创建或更新Polyline的positions。
  3. 保留Primitive性能优势:继续使用PolylineCollection批量绘制箭头,保证大量箭头场景下的性能。

修改后的代码

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;
scene.globe.depthTestAgainstTerrain = true;
var polylines = scene.primitives.add(new Cesium.PolylineCollection());

var centerLon = -42.25;
var centerLat = -22.25;
var angle = 47;
var distance = 50000;
var nPos = project(centerLat, centerLon, distance, angle);

// 收集需要采样地形的点
var pointsToSample = [
    Cesium.Cartographic.fromDegrees(centerLon, centerLat),
    Cesium.Cartographic.fromDegrees(nPos.lon, nPos.lat)
];

// 采样最详细的地形高度
Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, pointsToSample).then(function(sampledPoints) {
    // 将采样后的点转换为Cartesian3坐标
    var positions = sampledPoints.map(function(point) {
        return Cesium.Cartesian3.fromRadians(point.longitude, point.latitude, point.height);
    });

    // 添加箭头线
    polylines.add({
        positions: positions,
        material: Cesium.Material.fromType('PolylineArrow', {
            color: new Cesium.Color.fromBytes(255, 255, 0, 185)
        }),
        width: 15.0,
        // 手动贴地形后可关闭clampToGround
        clampToGround: false
    });
});

function project(lat, lon, distance, angle) {
    var radian = Cesium.Math.toRadians(angle);
    var ellipsoid = Cesium.Ellipsoid.WGS84;
    var firstPos = Cesium.Cartesian3.fromDegrees(lon, lat, 0);
    var ENU = Cesium.Transforms.eastNorthUpToFixedFrame(firstPos, ellipsoid);
    var offsetX = distance * Math.sin(radian);
    var offsetY = distance * Math.cos(radian);
    var offset = new Cesium.Cartesian3(offsetX, offsetY, 0);
    var thePosition = Cesium.Matrix4.multiplyByPoint(ENU, offset, new Cesium.Cartesian3());
    const cartographic = Cesium.Cartographic.fromCartesian(thePosition);
    const longitude = Cesium.Math.toDegrees(cartographic.longitude);
    const latitude = Cesium.Math.toDegrees(cartographic.latitude);
    return { lat: latitude, lon: longitude };
}

额外说明

  • 绘制大量箭头时,建议批量处理地形采样请求,避免频繁调用异步API影响性能。
  • 动态更新箭头位置时,需重新采样地形高度,确保线始终贴合真实地形。

内容的提问来源于stack exchange,提问作者Magno C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 10:55:23