Cesium绘制面

本文详细描述了如何使用Cesium库实现一个屏幕空间事件处理器,通过监听鼠标移动和点击事件,动态创建并管理点、线和面几何对象,用户可以绘制并删除图形。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

绘制面

// 绘制面
function setDrawPolygon() {
    let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);

    let movePosition = []; // 记录绘制过程中移动的点位置
    let moveEntity = null; // 记录绘制过程中移动的点实体
    let positions = []; // 记录左键点击的点位置
    let positionsLngLat = []
    let polygonEntity = null; // 记录面实体
    pointEntities = []; // 记录左键点击的点实体
    // 鼠标移动事件
    handler.setInputAction(event => {
        // 除第一次,每次移动都会删除上次的点实体
        moveEntity && viewer.entities.remove(moveEntity);
        // 每次移动,都会删除上次的移动点位置,置为空数组
        movePosition = [];
        // 每次移动都会记录当前点位置
        movePosition.push(transformation(event.endPosition));
        // 创建移动点实体
        viewer.entities.add({
            name: '点几何对象',
            position: movePosition[0],
            point: {
                color: Cesium.Color.YELLOW,
                pixelSize: 5,
                outlineColor: Cesium.Color.BLACK,
                outlineWidth: 2,
                disableDepthTestDistance: Number.POSITIVE_INFINITY,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
            },
        });
        // 记录点实体
        moveEntity = viewer.entities.values.slice(-1)[0];
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    // 点击左键事件
    handler.setInputAction(event => {
        // 记录左键点击的点实体位置
        positions.push(transformation(event.position));

        positionsLngLat.push(Cartesian3_to_WGS84(transformation(event.position)))
        // 如果左键已经点击产生了一个点,加上移动的点,已经能够构成一个线段了;
        if (positions.length === 1) {
            // 添加绘制的面实体
            polygonEntity = viewer.entities.add({
                name: "面几何对象",
                polygon: {
                    // 绘制动态面实体时,面的位置信息必须是使用 Cesium.CallbackProperty() 和 Cesium.PolygonHierarchy() 返回的坐标
                    hierarchy: new Cesium.CallbackProperty(function () {
                        return new Cesium.PolygonHierarchy(positions.concat(movePosition));
                    }, false),
                    material: Cesium.Color.fromCssColorString('yellow').withAlpha(0.2),
                },

                polyline: {
                    positions: new Cesium.CallbackProperty(function () {
                        return positions.concat(movePosition).concat([positions[0]]);
                    }, false),
                    material: Cesium.Color.RED.withAlpha(0.5),
                    // 必须给 golyline 设置贴地,否则会造成绘制的面和线在地图放大到一定程度后有误差
                    clampToGround: true,
                    width: 3,
                },
            });
        }
        // 添加点实体
        viewer.entities.add({
            position: transformation(event.position),
            point: {
                color: Cesium.Color.YELLOW,
                pixelSize: 5,
                outlineColor: Cesium.Color.BLACK,
                outlineWidth: 2,
                disableDepthTestDistance: Number.POSITIVE_INFINITY,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
            },
        });
        // 记录点实体
        pointEntities.push(viewer.entities.values.slice(-1)[0]);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    // 点击右键事件
    handler.setInputAction(() => {
        // 删除所有的点实体
        pointEntities.forEach(item => {
            viewer.entities.remove(item);
        });
        // 必须大于等于 3 个点才能创建面,否则删除
        if (positions.length >= 3) {
            addPolygon.push(polygonEntity);
            // 删除最后一个移动的点实体
            viewer.entities.remove(moveEntity);
            handler.destroy();
            clearAll()
        } else {
            viewer.entities.remove(polygonEntity);
            // 删除最后一个移动的点实体
            viewer.entities.remove(moveEntity);
            handler.destroy();
        };
        movePosition = []; // 控制最后右键点击的点是否保留
        activeType.value = false
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}


// 经纬度格式转为世界坐标格式的方法
function transformation(position) {
    if (!position) return [];
    return viewer.scene.globe.pick(viewer.camera.getPickRay(position), viewer.scene);
}


//删除所有点线面实体
function clearAll(){
    const entitys = viewer.entities._entities._array;
    let length = entitys.length
    for (let f = length - 1; f >= 0; f--) {
        if (entitys[f]._name && (entitys[f]._name === '点几何对象' || entitys[f]._name === '线几何对象' || entitys[f]._name === '面几何对象')) {
            viewer.entities.remove(entitys[f]);
        }
    }
}

### 绘制 Cesium 中的垂直平Cesium绘制垂直可以通过创建一个几何体并定义其法向量来实现。以下是具体方法: #### 使用 `Cesium.Plane` 定义平 Cesium 提供了一个名为 `Plane` 的类,用于表示三维空间中的无限平。可以利用这个类结合其他工具来构建所需的垂直平。 ```javascript // 创建一个通过原点并与 Y 轴平行的平 const normal = new Cesium.Cartesian3(0, 1, 0); // 法向量 (Y轴方向) const origin = new Cesium.Cartesian3(0, 0, 0); // 平经过的点 const distanceFromOrigin = 0; // 原点到平的距离 const plane = new Cesium.Plane(normal, distanceFromOrigin); ``` 上述代码片段展示了如何定义一个与 Y 轴正交并通过原点的平[^3]。 #### 渲染自定义几何体 为了渲染可见的垂直,通常需要创建一个多边形或矩形,并将其旋转至所需的方向。 ##### 方法一:使用 `Cesium.RectangleGraphics` 如果目标是一个简单的矩形区域,则可以直接使用 `RectangleGraphics` 来快速生成。 ```javascript viewer.entities.add({ rectangle: { coordinates: Cesium.Rectangle.fromDegrees( -100.0, 20.0, -90.0, 30.0 ), material: Cesium.Color.BLUE.withAlpha(0.5), outline: true, outlineColor: Cesium.Color.BLACK } }); ``` 此代码会生成一个蓝色半透明矩形,并带有黑色轮廓线[^4]。 ##### 方法二:手动设置顶点位置 对于更复杂的形状或者特定角度需求的情况,可通过指定四个角点坐标的方式构造多边形实体。 ```javascript const positions = [ Cesium.Cartesian3.fromDegrees(-75.0, 40.0, 0), Cesium.Cartesian3.fromDegrees(-75.0, 40.0, 100000), Cesium.Cartesian3.fromDegrees(-80.0, 40.0, 100000), Cesium.Cartesian3.fromDegrees(-80.0, 40.0, 0) ]; viewer.entities.add({ polygon : { hierarchy : new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArrayHeights([ ...positions.map(p => [p.longitude, p.latitude, p.height]).flat() ])), material : Cesium.Color.YELLOW.withAlpha(0.7) } }); ``` 这里我们定义了一组位于地球表及其上方一定高度处的四点作为边界框,从而形成竖直延伸的效果[^5]。 #### 注意事项 当调整这些对象的位置时,请注意它们相对于全球坐标的变换关系;另外还要考虑视图范围内的显示效果是否会受到影响。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值