CesiumJS 高频功能 —— 贴地

840 阅读2分钟

贴地是指将三维几何图形(如点、线、面)的位置固定在地形表面上,使得它们随着地形的起伏而起伏。在CesiumJS中,实现贴地效果是一项常见的需求,尤其是在处理地形数据时。贴地意味着将点、线、面等几何图形紧密贴合到地形表面,防止漂浮在空中,从而提供更加真实的视觉效果。

点、线、面的贴地实现

点的贴地

对于点(Point),贴地是通过设置 heightReference 属性实现的。heightReference 定义了实体相对于地球表面的高度参考,它可以取以下几个值:

  • Cesium.HeightReference.NONE:无高度参考,点将位于其局部空间内指定的高度。
  • Cesium.HeightReference.CLAMP_TO_GROUND:点将贴合到地形上,即与地形的高度对齐
  • Cesium.HeightReference.RELATIVE_TO_GROUND:实体的高度是相对于地形的,常用于需要在地形上方一定高度展示的实体。
viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(-122.1958, 46.1915),
    point: {
        color: Cesium.Color.SKYBLUE,
        pixelSize: 10,
        outlineColor: Cesium.Color.YELLOW,
        outlineWidth: 3,
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
    }
});

线的贴地

对于线(Polyline),贴地是通过设置 clampToGround 属性为 true 来实现的。这个属性表示线将随着地形的起伏而起伏,实现贴地效果。

viewer.entities.add({
    polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray([
            -122.19, 46.1914, -122.21, 46.21, -122.23, 46.21
        ]),
        width: 2,
        material: Cesium.Color.GREEN.withAlpha(0.5),
        clampToGround: true,
    }
});

面的贴地

对于面(Polygon),贴地设置稍微复杂一些。需要将 perPositionHeight 设置为 false,这样面的每个顶点就不会单独根据地形高度变化,而是整个面都贴合到地形上。同时,设置 heightReferenceCLAMP_TO_GROUND 确保面是贴在地形上的。

viewer.entities.add({
    polygon: {
        hierarchy: Cesium.Cartesian3.fromDegreesArray([
            -122.19, 46.1914, -122.21, 46.21, -122.23, 46.21
        ]),
        material: Cesium.Color.BLUE.withAlpha(0.5),
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
    }
});

模型

3D Tiles模型贴地

对于3D Tiles模型,贴地通常是通过调整模型矩阵(model matrix)来实现的。下述示例代码展示了如何通过设置模型矩阵来调整3D Tiles模型的高度,使其贴合地形:

var tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
    url: 'path/to/your/tileset.json',
}));

tileset.readyPromise.then(function(tileset) {
    var heightOffset = -210; // 根据实际情况调整高度偏移值
    var boundingSphere = tileset.boundingSphere;
    var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);
    var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0);
    var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);
    var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
    tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
});

实体(Entity)模型贴地

对于实体模型,可以通过设置 heightReference 属性为 CLAMP_TO_GROUND 来实现贴地效果:

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706),
    model: {
        uri: 'path/to/your/model.glb',
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
    }
});

贴模型

在CesiumJS中,classificationType 属性用于控制实体的绘制是否与地形或3D Tiles进行交互,从而实现不同的视觉效果。这个属性可以取以下几个值:

  1. Cesium.ClassificationType.TERRAIN:仅在地形上绘制。当设置为这个值时,实体(如多边形、线等)将只与地形进行交互,忽略3D Tiles的影响。
  2. Cesium.ClassificationType.CESIUM_3D_TILE:仅在3D Tiles上绘制。这意味着实体的绘制将只与3D Tiles相交,而不考虑地形的影响。
  3. Cesium.ClassificationType.BOTH:在地形和3D Tiles上都绘制。这是默认值,实体的绘制会同时考虑地形和3D Tiles的影响。
var polygonEntity = viewer.entities.add({
    polygon : {
        hierarchy : Cesium.Cartesian3.fromDegreesArray([
            -122.0744619, 44.0503706,
            -121.0744619, 44.0503706,
            -121.0744619, 43.0503706,
            -122.0744619, 43.0503706
        ]),
        material : Cesium.Color.GREEN.withAlpha(0.5),
        heightReference : Cesium.HeightReference.CLAMP_TO_GROUND,
        classificationType: Cesium.ClassificationType.BOTH
    }
});