cesium编程中级(五)贴地线

关于贴地线

整理一下官网示例中提到的各种贴地线,有些并不是线,而是多边形,可是可以通过宽度调整,表现成”线”

作为对比,先来加一个普通线段

var yellowLine = viewer.entities.add({
    name: 'Red line on the surface',
    polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray([
            112.82436,
            23.071506,
            112.82742,
            23.067512,
            112.828878,
            23.064659,
            112.830799,
            23.060947,
            112.832166,
            24.058329
        ]),
        width: 2,
        material: Cesium.Color.YELLOW
    }
});

这里为了看到效果,特意把最后一个点的纬度增大了,这个线并不是贴地的,因为在有些地方,它被地形挡住了

看第一种折中的“贴地线”

将上面代码的 “polyline” 改成“corridor”,这么改实际上是构建了一个corridor面对象,但是可以看到线段的所有位置都是在地表的,

但是这种方法会有一个问题,就是如果线上方有点云的话,点云颜色会被”线”影响(但是如果是面状geometry的话并不会被影响)

来看第二种贴地线

viewer.dataSources.add(Cesium.GeoJsonDataSource.load('http://localhost:1234/lesson07/pwt1/line.json', {
     clampToGround: true
}));

线段用json配置,点位和上面一致

显示后发现情况和第二种一样

看第三种

原理参考 法克鸡丝

var rectanglePrimitive = viewer.scene.primitives.add(new Cesium.GroundPrimitive({
    geometryInstances: new Cesium.GeometryInstance({
        geometry: new Cesium.CorridorGeometry({
            vertexFormat: Cesium.VertexFormat.POSITION_ONLY,
            positions: Cesium.Cartesian3.fromDegreesArray([112.82536, 23.071506, 112.82742, 23.067512, 112.828878, 23.064659, 112.830799, 23.060947, 112.832166, 23.058329]),
            width: 40
        }),
        attributes: {
            color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(0.0, 1.0, 0.0, 0.5))
        }
    }),
    classificationType: Cesium.ClassificationType.TERRAIN
}));

效果比较好,贴地而且不影响上面的点云,(可以理解为在地表贴了一个纹理,地表不显示,它也不显示):

第四种,来自官方示例 Ground Clamping

为方便大家查看,代码粘贴如下:

 function() {
    var length = 1000;

    var startLon = Cesium.Math.toRadians(86.953793);
    var endLon = Cesium.Math.toRadians(86.896497);

    var lat = Cesium.Math.toRadians(27.988257);

    var terrainSamplePositions = [];
    for (var i = 0; i < length; ++i) {
        var lon = Cesium.Math.lerp(endLon, startLon, i / (length - 1));
        var position = new Cesium.Cartographic(lon, lat);
        terrainSamplePositions.push(position);
    }

    Cesium.when(Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, terrainSamplePositions), function(samples) {
        var offset = 10.0;
        for (var i = 0; i < samples.length; ++i) {
            samples[i].height += offset;
        }

        viewer.entities.add({
            polyline : {
                positions : Cesium.Ellipsoid.WGS84.cartographicArrayToCartesianArray(samples),
                followSurface : false,
                width : 5,
                material : new Cesium.PolylineOutlineMaterialProperty({
                    color : Cesium.Color.ORANGE,
                    outlineWidth : 2,
                    outlineColor : Cesium.Color.BLACK
                }),
                depthFailMaterial : new Cesium.PolylineOutlineMaterialProperty({
                    color : Cesium.Color.RED,
                    outlineWidth : 2,
                    outlineColor : Cesium.Color.BLACK
                })
            }
        });

        var target = new Cesium.Cartesian3(300770.50872389384, 5634912.131394585, 2978152.2865545116);
        offset = new Cesium.Cartesian3(6344.974098678562, -793.3419798081741, 2499.9508860763162);
        viewer.camera.lookAt(target, offset);
        viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
    });
}

这个思路是在线段的首尾两点之间做插值,计算插值点点位的经纬度,保存在数组里面,然后通过地形信息将地形上对应点连成线

相关代码

2 thoughts to “cesium编程中级(五)贴地线”

  1. Uncaught TypeError: Cesium.when is not a function 会报错, 网上查说是cesium版本的问题, 请教有人解决了么?

发表评论

电子邮件地址不会被公开。 必填项已用*标注