Cesium绘制面

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

绘制面

// 绘制面
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.Primitive类型。以下是一个简单的示例,演示了如何使用Cesium.Primitive绘制一个三角形: ```javascript //创建顶点数组 var positions = [ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0 ]; //创建颜色数组 var colors = [ 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0 ]; //创建索引数组 var indices = [0, 1, 2]; //创建几何体 var geometry = new Cesium.Geometry({ attributes: { position: new Cesium.GeometryAttribute({ componentDatatype: Cesium.ComponentDatatype.DOUBLE, componentsPerAttribute: 3, values: positions }), color: new Cesium.GeometryAttribute({ componentDatatype: Cesium.ComponentDatatype.FLOAT, componentsPerAttribute: 4, values: colors }) }, indices: indices, primitiveType: Cesium.PrimitiveType.TRIANGLES }); //创建材质 var material = new Cesium.Material({ fabric: { type: 'Color', uniforms: { color: new Cesium.Color(1.0, 1.0, 1.0, 1.0) } } }); //创建渲染参数 var renderState = Cesium.RenderState.fromCache({ depthTest: { enabled: true }, depthMask: true, blending: Cesium.BlendingState.ALPHA_BLEND }); //创建几何体实例 var primitive = new Cesium.Primitive({ geometryInstances: new Cesium.GeometryInstance({ geometry: geometry, modelMatrix: Cesium.Matrix4.IDENTITY, attributes: { color: colors }, id: 'triangle' }), appearance: new Cesium.PerInstanceColorAppearance({ flat: true }), material: material, renderState: renderState }); //将几何体添加到场景中 viewer.scene.primitives.add(primitive); ``` 在上的示例中,我们创建了一个三角形的顶点、颜色和索引数组。然后,我们使用这些数组创建了一个Cesium.Geometry实例。接下来,我们创建了一个Cesium.Material实例和一个渲染参数Cesium.RenderState实例。最后,我们将Cesium.Geometry实例和Cesium.Material实例一起传递给Cesium.Primitive构造函数,并将其添加到场景中。 注意,上的示例仅绘制了一个三角形,如果您需要绘制更复杂的几何体,您需要创建更复杂的顶点和索引数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值