//高度测量类
import * as Cesium from 'cesium'
export default class MeasureHeight {
    constructor(viewer) {
        this.viewer = viewer;
        this.initEvents();
        this.positions = [];
        this.vertexEntities = [];
        this.labelEntity = undefined;
        this.measureHeight = 0; //测量结果
    }

    //初始化事件
    initEvents() {
        this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
        this.MeasureStartEvent = new Cesium.Event(); //开始事件
        this.MeasureEndEvent = new Cesium.Event(); //结束事件
    }

    //激活
    activate() {
        this.deactivate();
        this.registerEvents(); //注册鼠标事件
        //设置鼠标状态
        this.viewer.enableCursorStyle = false;
        this.viewer._element.style.cursor = 'default';
        this.isMeasure = true;
        this.circleRadius = 0.1;
        this.measureHeight = 0;
        this.positions = [];
    }

    //禁用
    deactivate() {
        if (!this.isMeasure) return;
        this.unRegisterEvents();
        this.viewer._element.style.cursor = 'pointer';
        this.viewer.enableCursorStyle = true;
        this.isMeasure = false;
    }

    //清空绘制
    clear() {
        //清除线对象
        this.viewer.entities.remove(this.lineEntity);
        this.lineEntity = undefined;

        //清除文本
        this.viewer.entities.remove(this.labelEntity);
        this.labelEntity = undefined;

        //移除圆
        this.removeCircleEntity();

        //清除节点
        this.vertexEntities.forEach(item => {
            this.viewer.entities.remove(item);
        });
        this.vertexEntities = [];
    }

    //创建线对象
    createLineEntity() {
        this.lineEntity = this.viewer.entities.add({
            polyline: {
                positions: new Cesium.CallbackProperty(e => {
                    return this.positions;
                }, false),
                width: 2,
                material: Cesium.Color.YELLOW,
                depthFailMaterial: new Cesium.PolylineDashMaterialProperty({
                    color: Cesium.Color.RED,
                }),
            }
        })
    }

    //创建结果文本标签
    createLabel() {
        this.labelEntity = this.viewer.entities.add({
            position: new Cesium.CallbackProperty(e => {
                return this.positions[this.positions.length - 1]; //返回最后一个点
            }, false),
            label: {
                text: "",
                scale: 0.5,
                font: 'normal 40px MicroSoft YaHei',
                distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000),
                scaleByDistance: new Cesium.NearFarScalar(500, 1, 1500, 0.4),
                verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                pixelOffset: new Cesium.Cartesian2(0, -30),
                outlineWidth: 9,
                outlineColor: Cesium.Color.WHITE
            }
        })
    }

    //创建线节点
    createVertex(index) {
        let vertexEntity = this.viewer.entities.add({
            position: new Cesium.CallbackProperty(e => {
                return this.positions[index];
            }, false),
            type: "MeasureHeightVertex",
            point: {
                color: Cesium.Color.FUCHSIA,
                pixelSize: 6,
                // disableDepthTestDistance: 2000,
            },
        });
        this.vertexEntities.push(vertexEntity);
    }

    //创建圆 这样方便看出水平面的高低
    createCircleEntitiy() {
        this.circleEntity = this.viewer.entities.add({
            position: new Cesium.CallbackProperty(e => {
                return this.positions[this.positions.length - 1]; //返回最后一个点
            }, false),
            ellipse: {
                height: new Cesium.CallbackProperty(e => {
                    return positionHeight(this.positions[this.positions.length - 1]);
                }, false),
                semiMinorAxis: new Cesium.CallbackProperty(e => {
                    return this.circleRadius;
                }, false),
                semiMajorAxis: new Cesium.CallbackProperty(e => {
                    return this.circleRadius;
                }, false),
                material: Cesium.Color.YELLOW.withAlpha(0.5),
            },
        });
    }

    //删除圆
    removeCircleEntity() {
        this.viewer.entities.remove(this.circleEntity);
        this.circleEntity = undefined;
    }

    //注册鼠标事件
    registerEvents() {
        this.leftClickEvent();
        this.rightClickEvent();
        this.mouseMoveEvent();
    }

    //左键点击事件
    leftClickEvent() {
        //单击鼠标左键画点点击事件
        this.handler.setInputAction(e => {
            this.viewer._element.style.cursor = 'default';
            let position = this.viewer.scene.pickPosition(e.position);
            if (!position) {
                const ellipsoid = this.viewer.scene.globe.ellipsoid;
                position = this.viewer.scene.camera.pickEllipsoid(e.position, ellipsoid);
            }
            if (!position) return;

            if (this.positions.length == 0) { //首次点击
                this.positions.push(position);
                this.createVertex(0);
                this.createLineEntity();
                this.createCircleEntitiy();
                this.createLabel();
            } else { //第二次点击结束测量
                this.measureEnd();
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    }

    //鼠标移动事件
    mouseMoveEvent() {
        this.handler.setInputAction(e => {
            if (!this.isMeasure) return;
            this.viewer._element.style.cursor = 'default';
            let position = this.viewer.scene.pickPosition(e.endPosition);
            if (!position) {
                position = this.viewer.scene.camera.pickEllipsoid(e.startPosition, this.viewer.scene.globe.ellipsoid);
            }
            if (!position) return;
            this.handleMoveEvent(position);
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }

    //处理鼠标移动
    handleMoveEvent(position) {
        if (this.positions.length < 1) return;
        let firstPoint = cartesian3Point3(this.positions[0]); //第一个点
        let movePoint = cartesian3Point3(position); //鼠标移动点
        const h = movePoint[2] - firstPoint[2];
        firstPoint[2] = movePoint[2];
        const twoPosition = Cesium.Cartesian3.fromDegrees(firstPoint[0], firstPoint[1], movePoint[2]);
        if (this.positions.length < 2) {
            this.positions.push(twoPosition);
            this.createVertex(1);
        } else {
            this.positions[1] = twoPosition;
            this.measureHeight = h.toFixed(3);
            this.labelEntity.label.text = "高度：" + this.measureHeight + " 米"
        }
        //计算圆的半径
        this.circleRadius = getDistanceH(this.positions[0], position);
    }

    //右键事件
    rightClickEvent() {
        this.handler.setInputAction(e => {
            if (this.isMeasure) {
                this.deactivate();
                this.clear();
            }
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    }

    //测量结束
    measureEnd() {
        this.deactivate();
        this.MeasureEndEvent.raiseEvent(this.measureHeight); //触发结束事件 传入结果
    }

    //解除鼠标事件
    unRegisterEvents() {
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }
}
将这段代码改为形如 distance(type) {
        //默认测空间
        type = type === undefined ? 0 : type;
        this._reset();
        this._lineParams.lineDataSource = new Cesium.CustomDataSource('lineDataSource');
        this.viewer.dataSources.add(this._lineParams.lineDataSource);
        this.viewer.scene.globe.depthTestAgainstTerrain = true;//开启深度测试
        this._distance_handler = new Cesium.ScreenSpaceEventHandler(this.viewer.canvas);
        //绑定鼠标左击事件
        //尝试过把下面的方法拿出来，但是总是找不到this对象。。。有缘人试试吧
        this._distance_handler.setInputAction((e) => {
            let pos = this.viewer.scene.pickPosition(e.position);//笛卡尔坐标
            if (pos) {
                this._lineParams.vertexCollection.push(pos);
            }
            //添加线
            let currentLine = this._lineParams.lineDataSource.entities.add({
                polyline: {
                    positions: new Cesium.CallbackProperty(() => {
                        let c = Array.from(this._lineParams.vertexCollection);
                        if (this._lineParams.mousePos) {
                            c.push(this._lineParams.mousePos);
                        }
                        return c
                    }, false),
                    clampToGround: true,//折线固定在地面
                    width: 3,
                    material: new Cesium.PolylineOutlineMaterialProperty({
                        color: new Cesium.Color(255 / 255, 118 / 255, 0 / 255, 1.0),
                        outlineColor: new Cesium.Color(255 / 255, 180 / 255, 115 / 255, 1.0),
                        outlineWidth: 2
                    })
                }
            })
            if (type == 0) {
                if (this._lineParams.vertexCollection.length >= 2) {
                    this._lineParams.totalLength += this._surfaceDistance(this._lineParams.vertexCollection[this._lineParams.vertexCollection.length - 2], pos);
                    this._lineParams.totalLength = parseFloat((this._lineParams.totalLength).toFixed(2));
                }
                this._addDistancePoint(pos, this._lineParams.totalLength)
            } else {
                if (this._lineParams.vertexCollection.length == 1) {
                    this._addDistancePoint(pos, this._lineParams.totalLength);
                } else {
                    let left = this._lineParams.vertexCollection[this._lineParams.vertexCollection.length - 2];
                    let right = pos;
                    //求两个顶点的直线距离，用于判断插值精度
                    let t = Cesium.Cartesian3.distance(left, right);
                    let vertexLength = this._terrianDistance(this._lineParams.vertexCollection[this._lineParams.vertexCollection.length - 2], pos, t);
                    this._lineParams.totalLength += vertexLength;
                    this._lineParams.totalLength = parseFloat((this._lineParams.totalLength).toFixed(2));
                    this._addDistancePoint(pos, this._lineParams.totalLength);
                }
            }
            if (this._lineParams.lastLine) {
                this._lineParams.lineDataSource.entities.remove(this._lineParams.lastLine)
            }
            this._lineParams.lastLine = currentLine;
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

        //鼠标移动事件
        this._distance_handler.setInputAction((e) => {
            let endPosition = e.endPosition;
            let endPos = this.viewer.scene.pickPosition(endPosition);
            if (endPos) {//鼠标移出地球,undifined
                this._lineParams.mousePos = endPos;
                //entity polyline 中使用了Cesium CallbackProperty 免去移动再画线
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)

        //鼠标右键事件，右键取消不在添加点计算面积
        this._distance_handler.setInputAction((e) => {
            let endPostion = e.position;
            let endPos = this.viewer.scene.pickPosition(endPostion);
            if (endPos) {
                this.cancel();
                // vertexCollection.push(endPos);
                // if(type==0){
                //     totalLength+=this._surfaceDistance(vertexCollection[vertexCollection.length-2],endPos);
                //     this._addDistancePoint(endPos,totalLength);
                // }else{
                //     let left = vertexCollection[vertexCollection.length-2];
                //     let right = endPos;
                //     //求两个顶点的直线距离，用于判断插值精度
                //     let t = Cesium.Cartesian3.distance(left,right);
                //     let vertexLength = this._terrianDistance(vertexCollection[vertexCollection.length-2],endPos,t);
                //     totalLength+=vertexLength;
                //     this._addDistancePoint(endPos,totalLength);
                // }
                this._lineParams.lineDataSource.entities.add({
                    polyline: {
                        clampToGround: true,
                        positions: this._lineParams.vertexCollection,
                        width: 3,
                        material: new Cesium.PolylineOutlineMaterialProperty({
                            color: new Cesium.Color(255 / 255, 118 / 255, 0 / 255, 1.0),
                            outlineColor: new Cesium.Color(255 / 255, 180 / 255, 115 / 255, 1.0),
                            outlineWidth: 2
                        })
                    }
                })
                if (this._lineParams.lastLine) {
                    this._lineParams.lineDataSource.entities.remove(this._lineParams.lastLine);
                }
                this._lineParams.vertexCollection = [];
                this._lineParams.mousePos = null;
            }
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
    }

    /**
     * 空间距离计算
     * @param start
     * @param end
     * @returns {number}
     * @private
     */
    _surfaceDistance(start, end) {//测地线（椭球上距离）
        let geodesic = new Cesium.EllipsoidGeodesic();
        let startGeodesic = Cesium.Cartographic.fromCartesian(start)//笛卡尔系转经纬度
        let endGeodesic = Cesium.Cartographic.fromCartesian(end)
        geodesic.setEndPoints(startGeodesic, endGeodesic)
        let lengthInMeters = (geodesic.surfaceDistance) / 1000;
        return parseFloat(lengthInMeters)
    }

    /**
     * 表面距离
     * @param start
     * @param end
     * @param t
     * @private
     */
    _terrianDistance(start, end, t) {
        let level = Math.ceil(Math.log10(t));
        let count = level * 5;
        let lerp = [];
        let vertexLength = 0;
        //两个端点加上count个插值点
        for (let i = 0; i <= count + 1; i++) {
            let pt = Cesium.Cartesian3.lerp(start, end, i / (count + 1), new Cesium.Cartesian3())//插值点
            let samplePt = this.viewer.scene.clampToHeight(pt)//高度采样点
            lerp.push(samplePt)
        }
        //计算折线长度
        for (let j = 1; j < lerp.length; j++) {
            let left = lerp[j - 1]
            let right = lerp[j]
            let length = Cesium.Cartesian3.distance(left, right)
            vertexLength += length
        }
        vertexLength = vertexLength / 1000;
        return vertexLength;
    }