Source: commands/CesiumDrawTool.js



import * as turf from "@turf/turf"
import { GUID } from "../util/util";


export const DrawingMode={
    DrawPolygon:"polygon",
    DrawLine:"line"
}

/**
 * 绘制线面的封装
 * @alias CesiumDrawTool
 */
export class CesiumDrawTool {
    /**
     * @param {function} _callback  绘制完成回调函数
     * @param {object} option  参数
     * @param {DrawMode} option.drawingMode  参数
     * @param {boolean} option.isclearwhencomplete  绘制完成后是否自行移除
     */
    constructor(_callback, option) {
        
        this.drawcomplete = _callback;

        //构造函数中作一些判断
        if (!viewer.scene.pickPositionSupported) {
            window.alert("This browser does not support pickPosition.");
        }
        //默认绘制线
        this.drawingMode = "line";
        if (option && option.drawingMode) {
            this.drawingMode = option.drawingMode;
        }
        //默认导出为4326参考系的点
        if (option && option.projection) {
            this.projection = option.projection ? option.projection : "EPSG:4326";
        }
        this.clampToGround = false;
        if (option && option.clampToGround) {
            this.clampToGround = option.clampToGround;
        }

        this.activeShapePoints = [];
        this.activeShape = undefined;
        this.activePoints = [];
        this.floatingPoint = undefined;

        this.handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
        //右键结束的时候是否清除对象
        this.isclearwhencomplete = true;
        if (option && option.isclearwhencomplete === false) {
            this.isclearwhencomplete = false;
        }
    }


    projectto(position) {
        var ellipsoid = viewer.scene.globe.ellipsoid;
        var cartesian3 = position;
        if(this._transform){
            cartesian3=Cesium.Matrix4.multiplyByPoint(this._transform,cartesian3,new Cesium.Cartesian3)
            return [cartesian3.x, cartesian3.y, cartesian3.z];
        }
        var cartographic = ellipsoid.cartesianToCartographic(cartesian3);
        var lat = Cesium.Math.toDegrees(cartographic.latitude);
        var lng = Cesium.Math.toDegrees(cartographic.longitude);
        var alt = cartographic.height;
        return [lng, lat, alt]
    }

    //设置转换
    setTransform(value){
        this._transform=value;
    }

    /**
     * 激活
     */
    active() {

        this.activeShapePoints = [];
        this.activeShape = undefined;
        this.activePoints = [];
        this.floatingPoint = undefined;
        //暂时不详
        // viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
        //     Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
        // );
        //必须开启深度测试,这时候桥在地形下方
        viewer.scene.globe.depthTestAgainstTerrain = true
        let that = this;

        this.handler.setInputAction(function (event) {
            // We use `viewer.scene.pickPosition` here instead of `viewer.camera.pickEllipsoid` so that
            // we get the correct point when mousing over terrain.
            var earthPosition = viewer.scene.pickPosition(event.position);
            // `earthPosition` will be undefined if our mouse is not over the globe.
            if (Cesium.defined(earthPosition)) {
                if (that.activeShapePoints.length === 0) {
                    that.floatingPoint = that.createPoint(earthPosition);
                    that.activeShapePoints.push(earthPosition);
                    var dynamicPositions = new Cesium.CallbackProperty(function () {
                        if (that.drawingMode === "polygon") {
                            return new Cesium.PolygonHierarchy(that.activeShapePoints);
                        }
                        return that.activeShapePoints;
                    }, false);
                    that.activeShape = that.drawShape(dynamicPositions);
                }
                that.activeShapePoints.push(earthPosition);
                that.activePoints.push(that.createPoint(earthPosition));
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

        this.handler.setInputAction(function (event) {
            if (Cesium.defined(that.floatingPoint)) {
                var newPosition = viewer.scene.pickPosition(event.endPosition);
                if (Cesium.defined(newPosition)) {
                    that.floatingPoint.position.setValue(newPosition);
                    that.activeShapePoints.pop();
                    that.activeShapePoints.push(newPosition);
                }
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);


        this.handler.setInputAction(function (event) {
            that.terminateShape();
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);




    }

    /**
     * 反激活
     */
    deactive() {
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
        //清除掉相关资源
        viewer.entities.remove(this.floatingPoint);
        viewer.entities.remove(this.activeShape);
        for (let index = 0; index < this.activePoints.length; index++) {
            const element = this.activePoints[index];
            viewer.entities.remove(element);
        }
        //

    }

    //右键结束
    terminateShape() {
        this.activeShapePoints.pop();
        var obj = this.drawShape(this.activeShapePoints);
        viewer.entities.remove(this.floatingPoint);
        viewer.entities.remove(this.activeShape);
        var that = this;
        //有值的时候才返回
        if (this.drawcomplete && this.activeShapePoints) {
            try {
                //多边形的点返回额外的起点
                let returnpoints = this.activeShapePoints;
                let geojson = undefined;
                if (this.drawingMode == "polygon") {
                    returnpoints = [].concat(this.activeShapePoints);
                    returnpoints.push(this.activeShapePoints[0]);
                    //转换成经纬度然后构造geojson
                    let coords = returnpoints.map(p => { return that.projectto(p) });
                    //给予一个随机guid作为名称,用于检索
                    geojson = turf.polygon([coords], { name: GUID() });
                }
                //转换成
                this.drawcomplete({
                    id: obj,
                    pos: returnpoints,
                    geojson: geojson
                })
            } catch (error) {
                console.log(error);
            }
        }
        if (this.isclearwhencomplete) {
            viewer.entities.remove(obj);
            for (let index = 0; index < this.activePoints.length; index++) {
                const element = this.activePoints[index];
                viewer.entities.remove(element);
            }
        }
        this.floatingPoint = undefined;
        this.activeShape = undefined;
        this.activeShapePoints = [];
        this.activePoints = [];

    }

    drawShape(positionData) {
        var shape;
        if (this.drawingMode === "line") {
            shape = viewer.entities.add({
                polyline: {
                    positions: positionData,
                    clampToGround: false,
                    width: 3,
                },
            });
        } else if (this.drawingMode === "polygon") {
            shape = viewer.entities.add({
                polygon: {
                    hierarchy: positionData,
                    material: new Cesium.ColorMaterialProperty(
                        Cesium.Color.ORANGERED.withAlpha(0.5)
                    ),
                    // clampToGround: this.clampToGround,此后的api将没有clamptogroup参数,使用perposition决定是否贴地
                    perPositionHeight: !this.clampToGround,
                },
            });
        }
        return shape;
    }

    //创建点
    createPoint(worldPosition) {
        var point = viewer.entities.add({
            position: worldPosition,
            point: {
                color: Cesium.Color.RED,
                pixelSize: 5,
                heightReference: Cesium.HeightReference.NONE,
            },
        });
        return point;
    }
}