赣州市洪水风险预警系统三维版本
guoshilong
2023-02-20 52c8ca8e31bb9aee13726d9c858dee1d11dcde87
widgets/FloodAnalysis/Widget.js
@@ -2,558 +2,867 @@
// Copyright © 2022 guoshilong. All Rights Reserved.
// 模块描述:洪水淹没分析
///////////////////////////////////////////////////////////////////////////
define([
   'dojo/_base/declare',
   'dojo/_base/lang',
   'dojo/_base/array',
   'dojo/_base/html',
   'dojo/topic',
   'jimu/BaseWidget',
   './Tooltip-div',
   './FloodAnalysis',
   'libs/layer/layer.js',
   'libs/turf/turf.min.js'
],
   function (declare,
      lang,
      array,
      html,
      topic,
      BaseWidget,
      tooltip,
      flood,
      layer,
      turf,
   ) {
      return declare([BaseWidget], {
         baseClass: 'jimu-widget-FloodAnalysis',
         name: 'FloodAnalysis',
         riverWidth: 300,
         riverHeight: 10,
         speed: 10,
         positions: [],
         sideRes: null,
         riverPrimitive: null,
         material: null,
         drawingPolyline: null,
         //绘制的多边形数组
         polygonCartesianArray:[],
         //canvas转换后的图片
         canvasImage:null,
         //房屋人口
         peoplePositionArray:[],
         startup: function () {
            this.inherited(arguments);
            var self = this;
define(['dojo/_base/declare',
    'dojo/_base/lang',
    'dojo/_base/array',
    'dojo/_base/html',
    "dojo/topic",
    'jimu/BaseWidget',
    'dojo/on',
    'dstore/Memory',
    'dstore/Trackable',
    'dgrid/Grid',
    'dgrid/Keyboard',
    'dgrid/Selection',
    'dgrid/Editor',
    'dstore/RequestMemory',
    'dgrid/test/data/createSyncStore',
    "libs/echarts/v4/echarts.min",
    'libs/layer/layer.js',
    'libs/turf/turf.min.js'], function (declare, lang, array, html, topic, BaseWidget, on, Memory, Trackable, Grid, Keyboard, Selection,Editor, RequestMemory, createSyncStore, echarts, layer, turf) {
    return declare([BaseWidget], {
        baseClass: 'jimu-widget-FloodAnalysis',
        name: 'FloodAnalysis',
        //渲染的点位
        pointEntities: [],
        //渲染的线
        drawingPolyline:null,
        //html元素
        analysisBtn: null,
        historyBtn: null,
        divFloodAnalysis: null,
        divFloodHistory: null,
        hdSelect: null,
        smxSelect: null,
        //河段下拉列表
        hdDataList: [],
        //水面线下拉列表
        smxDataList:[],
        //洪水分析表格数据
        analysisTableList: [],
        dgridSelectEvent:null,
        currentSelectHistoryData:null,
        //历史风险图表格数据
        historyTableList: [
            {name: "5年洪水淹没图"},
            {name: "10年洪水淹没图"},
            {name: "15年洪水淹没图"},
        ],
        //当前选中的河段
        currentHd: null,
        //当前选中的水面线
        currentSmxcode: "",
        //水文站最近的点
        currentNearPoint:null,
        //收起框打开状态
        isOpen: true,
        //api接口
        url: {
            riverwaySelectName: "http://localhost:82/blade-ycreal/riverway/selectName",
            waterlineSelectName: "http://localhost:82/blade-ycreal/waterline/selectName",
            childpage: "http://localhost:82/blade-ycreal/water/childpage",
            getCzByGlCodeByGlQdj: "http://localhost:82/blade-ycreal/waterline/getCzByGlCodeByGlQdj",
            getHistoryList: "http://localhost:82/blade-ycreal/inundationResult/list",
            saveHistoryData: "http://localhost:82/blade-ycreal/inundationResult/save",
            getCoordinatesMinQdj: "http://localhost:82/blade-ycreal/water/getCoordinatesMinQdj",
        },
        evaluateData: [
            {
                name: "<0.5",
                house: 35,
                population: 175,
                area: 12.888,
                value: 50.123
            },
            {
                name: "1.0-2.0",
                house: 70,
                population: 350,
                area: 24.456,
                value: 100.456
            },
            {
                name: "2.0-3.0",
                house: 20,
                population: 100,
                area: 8.551,
                value: 39.789
            }
        ],
        startup: function startup() {
            var self = this
            this.bindHtmlElement()
            //实时、预测改变事件
            $('input[type=radio][name=middleRadio]').change(function () {
                if (this.value == "realtime") {
                    $("#sw-input").prop('disabled', true);
                } else {
                    $("#sw-input").prop('disabled', false);
                }
                if ($('#smx-select').val())
                    self.getPointData($('#smx-select').val())
            })
            this.map.scene.globe.depthTestAgainstTerrain = true;
            //取消双击事件
            this.map.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
            //开始分析按钮点击事件
            $('#start-analysis-btn').click(function () {
                if (self.currentHd && self.currentSmxcode) {
                    self.drawWater('analysis')
                } else {
                    layer.msg("请先选择河段和水面线")
                }
            })
            //洪水淹没分析按钮点击事件
            this.analysisBtn.click(function () {
                self.analysisBtn.addClass('choose-button')
                self.analysisBtn.removeClass('unchoose-button')
                self.historyBtn.addClass('unchoose-button')
                self.historyBtn.removeClass('choose-button')
                self.divFloodHistory.hide()
                self.divFloodAnalysis.show()
                $('#history-pagination').hide()
                if (self.currentHd){
                    $('#analysis-pagination').show()
                }
            })
            //历史风险图按钮点击事件
            this.historyBtn.click(function () {
                self.historyBtn.addClass('choose-button')
                self.historyBtn.removeClass('unchoose-button')
                self.analysisBtn.addClass('unchoose-button')
                self.analysisBtn.removeClass('choose-button')
                self.divFloodAnalysis.hide()
                self.divFloodHistory.show()
                $('#analysis-pagination').hide()
                $('#history-pagination').show()
                //获取历史数据
                self.getHistoryList()
            })
            //河段输入框聚焦、失焦、输入事件
            $('#hd-input').focus(function () {
                $("#hd-select").show()
            })
            $('#hd-input').blur(function () {
                //隐藏域触发改变事件需要手动触发
                // $("#hd-select").val().change()
                setTimeout(function(){//有bug 需要延迟执行隐藏
                    $("#hd-select").hide()
                },300)
            })
            // 河段输入事件
            $('#hd-input').on("input", function () {
                var searchString = $('#hd-input').val()
                var filterArray = self.hdDataList.filter(e => {
                    return e.riverway.indexOf(searchString) != -1
                })
                self.hdSelect.find("option").remove();//添加新值 删除旧值
                filterArray.forEach(e => {
                    let v = ''
                    if (e.stnm) {
                        v += '-' + e.stnm.trim() + '站'
                    }
                    if (e.gl_qdj) {
                        v += '-起点距' + e.gl_qdj
                    }
                    self.hdSelect.append("<option value='" + JSON.stringify(e) + "'>" + e.riverway + v + "</option>");
                })
            })
            //水位输入事件
            $('#sw-input').on("input", function () {
                self.getYcSub()
            })
            //河段选择框改变事件
            this.hdSelect.change(function () {
                $("#hd-input").val($(this).find("option:selected").text());
                var selected = JSON.parse($(this).val())
                self.currentHd = selected
                self.getSmxData(selected.river_code, selected.default_smx)
                self.getMin(selected.default_smx,selected.gl_qdj)
                if (self.waterEntity)
                    self.map.entities.remove(self.waterEntity)
                //地图定位
                self.map.camera.flyTo({
                    destination: Cesium.Cartesian3.fromDegrees(selected.river_origin, selected.qd_lat, 50000),
                });
                self.hdSelect.hide()
            })
            //水面线选择框改变事件
            this.smxSelect.change(function () {
                var selected = $(this).val()
                self.getPointData(selected)
            })
            //水位输入框按下回车事件
            $('#sw-input').keypress(function (event) {
                if (event.which == 13) {
                    self.analysisTableList.forEach(e => {
                        e.sw = self.calculateSw(e.water, sw)
                    })
                    self.loadPagination(self.analysisTableList, "analysis-pagination")
                }
            })
            //搜索按钮点击事件
            $('#search-button').click(function () {
                let searchName = $('#search-name').val()
                let filterArray = self.historyTableList.filter(e => {
                    return e.name.indexOf(searchName) != -1
                })
                self.loadPagination(filterArray, "history-pagination")
            })
            $('#save-button').click(function () {
                self.confirmPopup()
                // self.floodAnalysisPopup()
            })
        },
        onOpen: function onOpen() {
            this.init()
            //面板打开的时候触发 (when open this panel trigger)
            this.map.scene.globe.baseColor = Cesium.Color.BLACK;
            //切换底图
            $($('div.cesium-viewer').find('.cesium-baseLayerPicker-choices')[0]).children('div:eq(0)').trigger('click');
            $($('div.cesium-viewer').find('.cesium-baseLayerPicker-choices')[1]).children('div:eq(2)').trigger('click');
            //设置地图初始位置
            this.map.camera.setView({
                destination: Cesium.Cartesian3.fromDegrees(116.016905, 25.884684, 10000),
            });
        },
        onClose: function onClose() {
            //面板关闭的时候触发 (when this panel is closed trigger)
            this.deleteEntities(this.pointEntities)
            if (this.drawingPolyline)
                this.map.entities.remove(this.drawingPolyline);
            if (this.waterEntity)
                this.map.entities.remove(this.waterEntity)
            this.map.scene.globe.baseColor = Cesium.Color.WHITE;
            $('#hd-select option').remove()
            $('#smx-select option').remove()
            $('#sw-input').val("")
            $('#hd-input').val("")
            //清空表格数据
            $('.analysis-box-list').empty();
            $('.history-box-list').empty();
            $('#analysis-pagination').hide()
            this.analysisTableList = []
        },
        onMinimize: function onMinimize() {
            this.resize();
        },
        onMaximize: function onMaximize() {
            this.resize();
        },
        resize: function resize() {
        },
        destroy: function destroy() {
            //销毁的时候触发
            //todo
            //do something before this func
            this.inherited(arguments);
        },
        //绑定html元素,方便操作
        bindHtmlElement: function () {
            this.analysisBtn = $('.analysis-button')
            this.historyBtn = $('.history-button')
            this.divFloodAnalysis = $('.flood-analysis')
            this.divFloodHistory = $('.flood-history')
            this.hdSelect = $('#hd-select')
            this.smxSelect = $('#smx-select')
        },
        //初始化
        init() {
            //重置html元素状态
            this.divFloodHistory.hide()
            this.divFloodAnalysis.show()
            $("input[type=radio][name=middleRadio][value='realtime']").prop('checked', 'checked')
            this.hdSelect.hide()
            $('.fold-btn').addClass('open')
            $('.fold-btn').removeClass('close')
            $('.content').show()
            $("#sw-input").prop('disabled', true);
            $('#search-name').val("")
            this.isOpen = true
            this.analysisBtn.addClass('choose-button')
            this.analysisBtn.removeClass('unchoose-button')
            this.historyBtn.removeClass('choose-button')
            this.historyBtn.addClass('unchoose-button')
            this.currentHd = null
            this.currentSmxcode = ""
            //获取河段数据
            this.getHdData()
        },
        //获取河段下拉数据
        getHdData() {
            const self = this
            $.ajax({
                url: self.url.riverwaySelectName,
                type: 'post',
                dataType: 'json',
                jsonp: 'callback',
                jsonpCallback: 'data',
                data: {},
                success: function (res) {
                    let data = res.data
                    self.hdDataList = data
                    self.hdSelect.find("option").remove();//添加新值 删除旧值
                    data.forEach(e => {
                        let v = ''
                        if (e.stnm) {
                            v += '-' + e.stnm.trim() + '站'
                        }
                        if (e.gl_qdj) {
                            v += '-起点距' + e.gl_qdj
                        }
                        self.hdSelect.append("<option value='" + JSON.stringify(e) + "'>" + e.riverway + v + "</option>");
                    })
                }
            });
        },
        //获取水面线数据
        getSmxData(hdid, defaultId) {
            const self = this
            $.ajax({
                url: self.url.waterlineSelectName,
                type: 'post',
                dataType: 'json',
                jsonp: 'callback',
                jsonpCallback: 'data',
                data: {
                    hdid: hdid
                },
                success: function (res) {
                    let data = res.data
                    self.smxDataList = data
                    self.smxSelect.find("option").remove();//添加新值 删除旧值
                    if (data.length <= 0) {
                        $('#flood-tbody').html("")
                        $('#analysis-pagination').hide()
                    }
                    data.forEach(e => {
                        self.smxSelect.append("<option value=" + e.smxcode + ">" + e.waterline + "</option>");
                        if (e.smxcode == defaultId) {
                            $("#smx-select option[value=" + e.smxcode + "] ").attr("selected", true)
                            self.smxSelect.trigger("change")
                        }
                    })
                }
            });
        },
        //获取点数据
        getPointData(smxcode) {
            this.currentSmxcode = smxcode
            const self = this
            $.ajax({
                url: self.url.childpage,
                type: 'get',
                dataType: 'json',
                jsonp: 'callback',
                jsonpCallback: 'data',
                data: {
                    parentId: smxcode,
                    size: 9999999
                },
                success: function (res) {
                    if (res.code == 200) {
                        let data = res.data.records
                        self.createPointAndLine(data,self.pointEntities)
                        self.analysisTableList = data
                        self.getSub(self.currentHd.id, self.currentSmxcode)
                    }
                }
            });
        },
        //创建点线
        createPointAndLine(data,pointEntities){
            this.deleteEntities(pointEntities)
            // 水面线连线
            let cartesians = []
            for (let i = 0; i < data.length; i++) {
                cartesians.push(new Cesium.Cartesian3.fromDegrees(data[i].lng, data[i].lat,data[i].sw))
                let temp = this.map.entities.add({
                    position: Cesium.Cartesian3.fromDegrees(data[i].lng, data[i].lat,data[i].sw),
                    point: {
                        color: Cesium.Color.RED,
                        pixelSize: 11,
                        //防止地形遮挡住点
                        disableDepthTestDistance: Number.POSITIVE_INFINITY,
                        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
                    },
                });
                // 清空使用
                pointEntities.push(temp)
            }
            // 先清空 后画线
            if (this.drawingPolyline){
                this.map.entities.remove(this.drawingPolyline);
            }
            let lineOpts = {
                polyline: {
                    positions: cartesians,
                    clampToGround: true,
                    width: 3,
                    color: "#279a9a"
                }
            };
            // 画线
            this.drawingPolyline = this.map.entities.add(lineOpts);
        },
        //获取历史风险图数据列表
        getHistoryList() {
            const self = this
            $.ajax({
                url: self.url.getHistoryList,
                type: 'get',
                dataType: 'json',
                jsonp: 'callback',
                jsonpCallback: 'data',
                data: {
                    name: "",
                    pageSize:999999999,
                },
                success: function (res) {
                    if (res.code == 200) {
                        let data = res.data.records
                        data.forEach(e=>{
                            e.smxVal = JSON.parse(e.smxVal)
                        })
                        self.historyTableList = data
                        self.loadPagination(data,"history-pagination")
                    }
                }
            });
        },
        /**
         * 加载分页器
         * @param tableData 需要加载的所有数据
         * @param pageElementId 分页html的id
         * @param tableElementId tbody id
         */
        loadPagination(tableData, pageElementId) {
            if (tableData.length <= 0 && pageElementId == "analysis-pagination") {
                $('#analysis-pagination').hide()
            }
            if (tableData.length <= 0 && pageElementId == "history-pagination") {
                $('#history-pagination').hide()
            }
            let pageSize = 10
            var count = Math.ceil(tableData.length / pageSize);
            var self = this
            $('#' + pageElementId).pagination({
                mode: 'fixed',
                jump: true,
                coping: false,
                pageCount: count,
                callback: function (index) {
                    var listdata = [];
                    //显示页数
                    var index = (index.getCurrent() - 1) * pageSize;
                    for (var i = index; i < index + pageSize; i++) {
                        listdata.push(tableData[i]);
                        if (i == tableData.length - 1) {
                            break;
                        }
                    }
                    pageElementId == "analysis-pagination" ? self.createList(listdata,"洪水淹没分析") : self.createList(listdata,"历史风险图")
                }
            });
            //首次加载前11条数据
            var startData = [];
            if (tableData.length > pageSize) {
                for (var i = 0; i < pageSize; i++) {
                    startData.push(tableData[i]);
                }
            } else {
                for (var i = 0; i < tableData.length; i++) {
                    startData.push(tableData[i]);
                }
            }
            pageElementId == "analysis-pagination" ? self.createList(startData,"洪水淹没分析") : self.createList(startData,"历史风险图")
        },
        /**
         * 计算水位
         * @param waterline 水面线高度
         * @param number 差值
         */
        calculateSw(waterline, sub) {
            let sw = this.floatAdd(Number(waterline), Number(sub))
            return sw
        },
        //预测水位计算
        getYcSub() {
            const self = this
            self.analysisTableList.forEach(e => {
                e.lng = Number(e.lng).toFixed(4)
                e.lat = Number(e.lat).toFixed(4)
                e.sw = self.calculateSw(e.water, $('#sw-input').val())
                e.water = Number(e.water).toFixed(3)
                e.sw = Number(e.sw).toFixed(3)
            })
            self.loadPagination(self.analysisTableList, "analysis-pagination")
        },
        //实时水位计算
        getSub(hdid, smxcode) {
            const self = this
            if ($('input[name=middleRadio]:checked').val() == 'realtime') {
                $.ajax({
                    url: self.url.getCzByGlCodeByGlQdj,
                    type: 'get',
                    dataType: 'json',
                    jsonp: 'callback',
                    jsonpCallback: 'data',
                    data: {
                        hdId: hdid,
                        smxcode: smxcode
                    },
                    success: function (res) {
                        if (res.code == 200) {
                            let sub = res.data
                            $('#sw-input').val(sub)
                            self.analysisTableList.forEach(e => {
                                e.lng = Number(e.lng).toFixed(4)
                                e.lat = Number(e.lat).toFixed(4)
                                e.sw = self.calculateSw(e.water, sub)
                                e.water = Number(e.water).toFixed(3)
                                e.sw = Number(e.sw).toFixed(3)
                            })
                            self.loadPagination(self.analysisTableList, "analysis-pagination")
                        }
                    }
                });
            } else {
                self.getYcSub()
            }
        },
        //获取最接近水文站的值
        getMin(smxcode, glQdj) {
            const self = this
            $.ajax({
                url: self.url.getCoordinatesMinQdj,
                type: 'get',
                dataType: 'json',
                jsonp: 'callback',
                jsonpCallback: 'data',
                data: {
                    smxcode:smxcode,
                    glQdj:glQdj
                },
                success: function (res) {
                    if (res.code == 200) {
                        self.currentNearPoint = res.data
                    }
                }
            });
        },
        //保存历史风险图
        saveHistoryData() {
            const self = this
            $.ajax({
                url: self.url.saveHistoryData,
                type: 'get',
                dataType: 'json',
                jsonp: 'callback',
                jsonpCallback: 'data',
                data: {},
                success: function (res) {
                    if (res.code == 200) {
                        self.getHistoryList()
                    }
                }
            });
        },
        //防止出现两个小数相加出现很多0的情况
        floatAdd(arg1, arg2) {
            var r1, r2, m;
            try {
                r1 = arg1.toString().split(".")[1].length;
            } catch (e) {
                r1 = 0;
            }
            try {
                r2 = arg2.toString().split(".")[1].length;
            } catch (e) {
                r2 = 0;
            }
            m = Math.pow(10, Math.max(r1, r2));
            return (arg1 * m + arg2 * m) / m;
        },
        //删除地图上的标注点位
        deleteEntities(entities) {
            entities.forEach(e => {
                this.map.entities.remove(e)
            })
            entities = []
        },
        //评估分析弹窗
        evaluatePopup(flag) {
            var self = this
            let selectSmx = this.smxDataList.filter(e=>{
                return e.smxcode == this.currentSmxcode
            })
            let isAnalysis = flag == 'analysis'?true:false
            let parentData = {}
            if (isAnalysis){
                parentData.data = this.evaluateData
                parentData.hd = this.currentHd
                parentData.smx = selectSmx[0]
                parentData.sw = $('#sw-input').val()
                parentData.point = this.analysisTableList
            }else {
                parentData.data = this.evaluateData
                parentData.hd = this.currentSelectHistoryData.smxVal.hd
                parentData.smx = this.currentSelectHistoryData.smxVal.smx
                parentData.sw = this.currentSelectHistoryData.smxVal.sw
                parentData.point = this.currentSelectHistoryData.smxVal.point
            }
            $("#flood_hzsm_headtab").click(function () {
               DrawDynamicClampGround.startDrawingPolyline(self.map, function (cartesians) {
                  if (self.drawingPolyline != undefined)
                     self.map.entities.remove(self.drawingPolyline);
                  var lineOpts = {
                     polyline: {
                        positions: cartesians,
                        clampToGround: true,
                        width: 3,
                        color: "#279a9a"
                     }
                  };
                  self.drawingPolyline = self.map.entities.add(lineOpts);
                  cartesians.splice(cartesians.length - 1, cartesians.length);
                  self.drawLines(cartesians);
                  self.movehandLer()
               });
            });
            var url = './corelib/common/popup/evaluateAnalysis.html'
            var top = ($(window).height() - 550) / 2;
            var left = ($(window).width() - 400 - 340) / 2 + 340;
            layer.open({
                title: '评估分析',
                type: 2,
                maxmin: false, //开启最大化最小化按钮
                area: ['900px', '600px'],
                skin: 'floodAnalysis',
                offset: [top,left],
                content: url + "?parentData=" + encodeURIComponent(JSON.stringify(parentData)),//使用encodeURIComponent转码,避免中文字符乱码,避免url截取错误
                id: "floodAnalysisLayer",
                closeBtn: 1,
                success:function (layero,index) {
                    //绑定父子之间的关系,用于数据传递,缺少则无法传递
                    var body = layer.getChildFrame("body", index);
                    //得到iframe页的窗口对象
                    var iframeWin = window[layero.find('iframe')[0]['name']];
            $('#flood_qcsmx_headtab').click(function () {
               self.map.entities.remove(self.drawingPolyline);
               self.map.scene.primitives.remove(self.riverPrimitive);
            })
                    if (isAnalysis){
                        iframeWin.$('#save-btn').show()
                    }else {
                        iframeWin.$('#save-btn').hide()
                    }
                }
            });
        },
        //http://dgrid.io/tutorials/1.0/hello_dgrid/    创建表格
        createList: function (dataList, txt) {
            const self = this
            var CustomGrid = declare([Grid, Keyboard, Selection,Editor]);
            var column, tab, moon, dauy;
            var formatter = function (value,object) {
                if (self.currentNearPoint.id == object.id) {
                    return '<span style="color:red">' + value + '</span>'
                } else {
                    return value
                }
            }
            if (txt == "洪水淹没分析") {
                $('.analysis-box-list').empty();
                column = {
                    location: {
                        label:'位置',
                        formatter:formatter
                    },
                    origin: {
                        label:'起点距',
                        formatter:formatter
                    },
                    water: {
                        label:'水面线',
                        formatter:formatter
                    },
                    sw: {
                        label:'水位',
                        formatter:formatter
                    },
                    lng:{
                        label:'经度',
                        formatter:formatter
                    },
                    lat:{
                        label:'纬度',
                        formatter:formatter
                    },
                }
                tab = 'analysis-tab1-grid'
            } else if (txt == "历史风险图") {
                $('.history-box-list').empty();
                column = {
                    // radio:{ label: "", field: "radio", editor: 'radio' },
                    name: '名称',
                }
                tab = 'history-tab2-grid'
            }
            var grid = new CustomGrid({
                columns: column,
                selectionMode: 'single', // for Selection; only select a single row at a time
                cellNavigation: false, // for Keyboard; allow only row-level keyboard navigation
            }, tab);
            grid.startup();
            // $("#thematic_hlkd_headtab").change(function (e) {
            //    self.riverWidth = Number($(this).val());
            //    self.resetPos();
            // });
            $("#flood_analysis_sw_headtab").change(function (e) {
               self.riverHeight = Number($(this).val());
               self.resetPos();
            });
            // $("#thematic_sls_headtab").change(function (e) {
            //    self.speed = Number($(this).val());
            //    self.resetPos();
            // });
            //
            // $("#thematic_smsz_headtab").click(function () {
            //    self.offsetHeight(Number($("#thematic_bhz_headtab").val()), 5);
            // });
            //
            // $("#thematic_smxj_headtab").click(function () {
            //    self.offsetHeight(-Number($("#thematic_bhz_headtab").val()), 5);
            // });
            //change事件
            // grid.on("dgrid-datachange", function(evt){
            //     //获取行数据
            //     let data = evt.cell.row.data
            // });
            if (this.dgridSelectEvent){
                this.dgridSelectEvent.remove()
            }
         },
         init: function () {
            this.prepareVertex();
            if (this.sideRes) {
               this.material = this.prepareMaterial();
               this.riverPrimitive && this.map.scene.primitives.remove(this.riverPrimitive);
               this.riverPrimitive = this.createPrimitive();
               this.map.scene.primitives.add(this.riverPrimitive);
            }
         },
         prepareVertex: function () {
            if (this.positions.length > 0) {
               this.sideRes = this._lines2Plane(this.positions, this.riverWidth, this.riverHeight);
               console.log(this.sideRes,"----000----")
            }
         },
         setPositions: function (e) {
            this.positions = e;
            this.init();
         },
         resetPos: function () {
            this.sideRes = this._lines2Plane(this.positions, this.riverWidth, this.riverHeight);
            if (this.sideRes) {
               this.material = this.prepareMaterial();
               this.riverPrimitive && this.map.scene.primitives.remove(this.riverPrimitive);
               this.riverPrimitive = this.createPrimitive();
               this.map.scene.primitives.add(this.riverPrimitive);
            }
         },
         drawLines: function (r) {
            this.setPositions(r);
         },
         prepareMaterial: function () {
            var e = new Cesium.Material({
               fabric: {
                  uniforms: {
                     image: "widgets/ThematicDynamicRiver/images/movingRiver.png",
                     alpha: 0.5,
                     moveVar: new Cesium.Cartesian3(50, 1, 100),
                     reflux: -1,
                     speed: this.speed,
                     move: true,
                     flipY: false
                  },
                  source: "czm_material czm_getMaterial(czm_materialInput materialInput) { \n                        czm_material material = czm_getDefaultMaterial(materialInput); \n                        vec2 st = materialInput.st;\n                        if(move){\n                            float r = sqrt((st.x-0.8)*(st.x-0.8) + (st.y-0.8)*(st.y-0.8));\n                            float r2 = sqrt((st.x-0.2)*(st.x-0.2) + (st.y-0.2)*(st.y-0.2));\n                            float z = cos(moveVar.x*r + czm_frameNumber/100.0*moveVar.y)/moveVar.z;\n                            float z2 = cos(moveVar.x*r2 + czm_frameNumber/100.0*moveVar.y)/moveVar.z;\n                            st += sqrt(z*z+z2*z2);\n                            st.s += reflux * czm_frameNumber/1000.0 * speed;\n                            st.s = mod(st.s,1.0);\n                        }\n                        if(flipY){\n                            st = vec2(st.t,st.s);\n                        }\n                        vec4 colorImage = texture2D(image, st);\n                        material.alpha = alpha;\n                        material.diffuse = colorImage.rgb; \n                        return material; \n                    }"
               }
            });
            return e
         },
         createPrimitive: function () {
            var t = new Float64Array(this.sideRes.vertexs),
               i = new Cesium.GeometryAttributes;
            i.position = new Cesium.GeometryAttribute({
               componentDatatype: Cesium.ComponentDatatype.DOUBLE,
               componentsPerAttribute: 3,
               values: t
            }),
               i.st = new Cesium.GeometryAttribute({
                  componentDatatype: Cesium.ComponentDatatype.FLOAT,
                  componentsPerAttribute: 2,
                  values: this.sideRes.uvs
               });
            var r = new Cesium.Geometry({
               attributes: i,
               indices: this.sideRes.indexs,
               primitiveType: Cesium.PrimitiveType.TRIANGLES,
               boundingSphere: Cesium.BoundingSphere.fromVertices(t)
            }),
               n = new Cesium.GeometryInstance({
                  geometry: r
               }),
               o = new Cesium.RenderState;
            return o.depthTest.enabled = !0, new Cesium.Primitive({
               geometryInstances: n,
               appearance: new Cesium.Appearance({
                  material: this.material,
                  renderState: o,
                  vertexShaderSource: "attribute vec3 position3DHigh;\n                attribute vec3 position3DLow;\n                attribute vec2 st;\n                attribute float batchId;\n                \n                varying vec3 v_positionMC;\n                varying vec3 v_positionEC;\n                varying vec2 v_st;\n                \n                void main()\n                {\n                    vec4 p = czm_computePosition();\n                \n                    v_positionMC = position3DHigh + position3DLow;           // position in model coordinates\n                    v_positionEC = (czm_modelViewRelativeToEye * p).xyz;     // position in eye coordinates\n                    v_st = st;\n                \n                    gl_Position = czm_modelViewProjectionRelativeToEye * p;\n                }\n                ",
                  fragmentShaderSource: "varying vec3 v_positionMC;\n                varying vec3 v_positionEC;\n                varying vec2 v_st;\n                \n                void main()\n                {\n                    czm_materialInput materialInput;\n                \n                    vec3 normalEC = normalize(czm_normal3D * czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0)));\n                #ifdef FACE_FORWARD\n                    normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\n                #endif\n                \n                    materialInput.s = v_st.s;\n                    materialInput.st = v_st;\n                    materialInput.str = vec3(v_st, 0.0);\n                \n                    // Convert tangent space material normal to eye space\n                    materialInput.normalEC = normalEC;\n                    materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(v_positionMC, materialInput.normalEC);\n                \n                    // Convert view vector to world space\n                    vec3 positionToEyeEC = -v_positionEC;\n                    materialInput.positionToEyeEC = positionToEyeEC;\n                \n                    czm_material material = czm_getMaterial(materialInput);\n                \n                #ifdef FLAT\n                    gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n                #else\n                    gl_FragColor = czm_phong(normalize(positionToEyeEC), material,czm_lightDirectionEC);\n                #endif\n                }\n                "
               })
            })
         },
         offsetHeight: function (height, time) {
            this.startDH(height, time)
         },
         startDH: function (height, time) {
            if (height && time && this.riverPrimitive) {
               for (var i = this, r = 0, n = height / (20 * time), o = this.sideRes.self, s = new Cesium.Cartesian3, l = 0, u = o.length; l < u; l++) {
                  var c = Cesium.Cartesian3.normalize(o[l], new Cesium.Cartesian3);
                  Cesium.Cartesian3.add(s, c, s)
               }
               Cesium.Cartesian3.normalize(s, s);
               var h = Cesium.clone(this.riverPrimitive.modelMatrix);
               this.dhEvent = function () {
                  if (Math.abs(r) <= Math.abs(height)) {
                     var t = Cesium.Cartesian3.multiplyByScalar(s, r, new Cesium.Cartesian3);
                     i.riverPrimitive.modelMatrix = Cesium.Matrix4.multiplyByTranslation(h, t, new Cesium.Matrix4)
                  } else i.map.clock.onTick.removeEventListener(i.dhEvent);
                  r += n
               }, this.map.clock.onTick.addEventListener(this.dhEvent)
            }
         },
         //水面线转成水面
         _lines2Plane: function (positions, width, height) {
            function n(point, height) {
               if (!(point instanceof Cesium.Cartesian3)) return void console.log("请确认点是Cartesian3类型!");
               if (!height || 0 == height) return void console.log("请确认高度是非零数值!");
               var i = Cesium.Cartesian3.normalize(point, new Cesium.Cartesian3),
                  r = new Cesium.Ray(point, i);//射线
               return Cesium.Ray.getPoint(r, height)
            }
            this.dgridSelectEvent = grid.on("dgrid-select", function(evt){
                //获取行数据
                let data = evt.rows[0].data
                self.currentSelectHistoryData = data
                if (data.smxVal.point.length>0){
            function o(point, point1, height) {
               var r = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(point1, point, new Cesium.Cartesian3), new Cesium.Cartesian3),
                  n = Cesium.Cartesian3.normalize(point, new Cesium.Cartesian3),
                  o = Cesium.Cartesian3.cross(n, r, new Cesium.Cartesian3),
                  a = Cesium.Cartesian3.cross(r, n, new Cesium.Cartesian3),
                  l = new Cesium.Ray(point, o),
                  u = new Cesium.Ray(point, a);
               return {
                  left: Cesium.Ray.getPoint(l, height),
                  right: Cesium.Ray.getPoint(u, height)
               }
            }
                    self.deleteEntities(self.pointEntities)
                    if (self.drawingPolyline)
                        self.map.entities.remove(self.drawingPolyline);
            if (!positions || positions.length <= 1 || !width || 0 == width) return void console.log("请确认参数符合规则:数组长度大于1,宽高不能为0!");
            for (var r = positions.length, a = [], l = [], u = width / 2, c = 0; c < r; c++) {
               var h = void 0,
                  d = void 0,
                  f = void 0,
                  p = void 0,
                  m = void 0;
               if (0 == c ? (h = positions[c], d = positions[c], f = positions[c + 1]) : c == r - 1 ? (h = positions[c - 1], d = positions[c], f = positions[c - 1]) : (h = positions[c - 1], d = positions[c], f = positions[c + 1]), 0 != height && (h = n(h, height), d = n(d, height), f = n(f, height)), h && d && f) {
                  var g = o(d, f, u);
                  if (p = g.left, m = g.right, 0 == c) {
                     a.push(p), l.push(m), a.push(p), l.push(m);
                     continue
                  }
                  if (!(c < r - 1)) {
                     a.push(m), l.push(p), a.push(m), l.push(p);
                     continue
                  }
                  a.push(p), l.push(m), g = o(d, h, u), p = g.left, m = g.right, a.push(m), l.push(p)
               }
            }
                    if (self.waterEntity)
                        self.map.entities.remove(self.waterEntity)
            var v = [],
               y = [];
            if (a.length != 2 * r) return void console.log("计算左右侧点出问题!");
            for (var _ = 0; _ < r; _++) {
               var w = positions[_],
                  b = a[2 * _ + 0],
                  C = a[2 * _ + 1],
                  x = Cesium.Cartesian3.subtract(b, w, new Cesium.Cartesian3),
                  P = Cesium.Cartesian3.subtract(C, w, new Cesium.Cartesian3),
                  M = Cesium.Cartesian3.add(x, P, new Cesium.Cartesian3),
                  E = Cesium.Cartesian3.add(w, M, new Cesium.Cartesian3);
               v.push(Cesium.clone(E));
               var T = l[2 * _ + 0],
                  S = l[2 * _ + 1];
               x = Cesium.Cartesian3.subtract(T, w, new Cesium.Cartesian3), P = Cesium.Cartesian3.subtract(S, w, new Cesium.Cartesian3), M = Cesium.Cartesian3.add(x, P, new Cesium.Cartesian3), E = Cesium.Cartesian3.add(w, M, new Cesium.Cartesian3), y.push(Cesium.clone(E))
            }
                    $('#sw-input').val("")
                    $('#hd-input').val("")
                    $('#smx-select option').remove()
                    //清空表格数据
                    $('.analysis-box-list').empty();
                    $('#analysis-pagination').hide()
            for (var O = [], D = [], k = [], A = [], R = [], F = 0; F < r; F++) {
               var L = Cesium.EncodedCartesian3.fromCartesian(y[F]);
               D.push(y[F].x), D.push(y[F].y), D.push(y[F].z), k.push(L.high.x), k.push(L.high.y), k.push(L.high.z), A.push(L.low.x), A.push(L.low.y), A.push(L.low.z), O.push(1, 1), F < r - 1 && (R.push(F + 2 * r), R.push(F + 1), R.push(F + 1 + r), R.push(F + 2 * r), R.push(F + 1 + r), R.push(r + F + 2 * r))
            }
                    self.analysisTableList = []
            for (var I = 0; I < r; I++) {
               var N = Cesium.EncodedCartesian3.fromCartesian(v[I]);
               D.push(v[I].x), D.push(v[I].y), D.push(v[I].z), k.push(N.high.x), k.push(N.high.y), k.push(N.high.z), A.push(N.low.x), A.push(N.low.y), A.push(N.low.z), O.push(1, 0)
            }
                    self.createPointAndLine(data.smxVal.point,self.pointEntities)
            for (var V = 0; V < r; V++) {
               var z = Cesium.EncodedCartesian3.fromCartesian(y[V]);
               D.push(y[V].x), D.push(y[V].y), D.push(y[V].z), k.push(z.high.x), k.push(z.high.y), k.push(z.high.z), A.push(z.low.x), A.push(z.low.y), A.push(z.low.z), O.push(0, 1)
            }
                    self.map.camera.flyTo({
                        destination: Cesium.Cartesian3.fromDegrees(data.lon, data.lat, 50000),
                    });
            for (var H = 0; H < r; H++) {
               var B = Cesium.EncodedCartesian3.fromCartesian(v[H]);
               D.push(v[H].x), D.push(v[H].y), D.push(v[H].z), k.push(B.high.x), k.push(B.high.y), k.push(B.high.z), A.push(B.low.x), A.push(B.low.y), A.push(B.low.z), O.push(0, 0)
            }
                    self.drawWater('history')
                }
            this.polygonCartesianArray = []
            for (let i = 0; i < y.length; i++) {
               this.polygonCartesianArray.push(y[i])
            }
            for (let i = 0; i < v.length; i++) {
               this.polygonCartesianArray.push(v[i])
            }
            //计算polygon面积
            this.getPolygonArea(this.getPositionArray(this.polygonCartesianArray),this.polygonCartesianArray)
            });
            grid.renderArray(dataList);
        },
        // 洪水淹没效果
        drawWater(flag) {
            //地图定位
            // this.map.camera.flyTo({
            //     destination: Cesium.Cartesian3.fromDegrees(115.93791, 25.989108, 5000),
            // });
            //显示进度条
            $('.dong-progress .container #progress_bar').width(0);
            $('.dong-progress').stop().hide();
            return {
               left: v,
               right: y,
               self: positions,
               vertexs: new Float32Array(D),
               vertexsH: new Float32Array(k),
               vertexsL: new Float32Array(A),
               indexs: new Uint16Array(R),
               uvs: new Float32Array(O)
            }
         },
         onOpen: function () {
            //面板打开的时候触发 (when open this panel trigger)
            this.map.scene.globe.baseColor = Cesium.Color.BLACK;
            //初始化点
            this.addPoint()
            $($('div.cesium-viewer').find('.cesium-baseLayerPicker-choices')[0]).children('div:eq(3)').trigger('click');
            this.showWater = true
            this.waterEntity && this.map.entities.remove(this.waterEntity)
            const waterCoord = [116.0072, 25.9058, 100, 116.0546, 25.9012, 100 , 116.0457, 25.8611, 100, 115.9859, 25.8740 ,100]
            let startHeight = 169
            const targetHeight = 200
            this.waterEntity = this.map.entities.add({
                polygon: {
                    hierarchy: Cesium.Cartesian3.fromDegreesArrayHeights(waterCoord),
                    material: Cesium.Color.fromBytes(64, 157, 253, 200),
                    perPositionHeight: true,
                    extrudedHeight: new Cesium.CallbackProperty(() => { return startHeight }, false)
                }
            })
            $('.dong-progress').stop().show();
            // 总长度
            var totalWidth = $('.dong-progress .container').width();
            // 过度长度
            var excessiveWidth = totalWidth / 100;
            var watchWidth = 0;
            // 进度条的定时器
            var proTime = setInterval(function () {
                watchWidth += excessiveWidth;
                if (watchWidth > totalWidth) {
                    watchWidth = totalWidth;
                }
                $('.dong-progress .container #progress_bar').width(watchWidth);
            }, 22);
            const waterInterval = setInterval(() => {
                if (startHeight < targetHeight) {
                    startHeight += 5
                    if (startHeight >= targetHeight) {
                        startHeight = targetHeight
                        clearInterval(waterInterval)
         },
                        if (watchWidth < totalWidth) {
                            watchWidth = totalWidth;
                        }
                        clearInterval(proTime);
                        //隐藏进度条
                        $('.dong-progress .container #progress_bar').width(0);
                        $('.dong-progress').stop().hide();
                        this.showWater = false
                        this.evaluatePopup(flag)
                    }
                    // 使用该方式会闪烁,改用 Cesium.CallbackProperty 平滑
                    // this.waterEntity.polygon.extrudedHeight = startHeight
                }
            }, 1000*0.5)
        }
         onClose: function () {
            //面板关闭的时候触发 (when this panel is closed trigger)
            this.map.entities.remove(this.drawingPolyline);
            this.map.scene.primitives.remove(this.riverPrimitive);
            this.map.entities.removeAll()
         },
         onMinimize: function () {
            this.resize();
         },
         onMaximize: function () {
            this.resize();
         },
         resize: function () {
         },
         destroy: function () {
            //销毁的时候触发
            //todo
            //do something before this func
            this.inherited(arguments);
         },
         //Cartesian3转换为经纬度
         getPositionArray:function (cartesiansArray){
            var positionArray = []
            if (cartesiansArray.length>0){
               for (let i = 0; i < cartesiansArray.length; i++) {
                  //获取的对象中的经纬度为弧度
                  let cartographic= Cesium.Cartographic.fromCartesian(cartesiansArray[i])
                  //弧度转换
                  let longitude = Cesium.Math.toDegrees(cartographic.longitude)
                  let latitude = Cesium.Math.toDegrees(cartographic.latitude)
                  let height = cartographic.height
                  positionArray.push({
                     lon:longitude,
                     lat:latitude,
                     hei:height,
                  })
               }
            }
            return positionArray
         },
         //获取多边形面积
         getPolygonArea:function (points,positions){
            let radiansPerDegree = Math.PI / 180.0;//角度转化为弧度(rad)
            let degreesPerRadian = 180.0 / Math.PI;//弧度转化为角度
            //计算多边形面积
            function getArea(points) {
               let res = 0;
               //拆分三角曲面
               for (let i = 0; i < points.length - 2; i++) {
                  let j = (i + 1) % points.length;
                  let k = (i + 2) % points.length;
                  let totalAngle = Angle(points[i], points[j], points[k]);
                  let dis_temp1 = distance(positions[i], positions[j]);
                  let dis_temp2 = distance(positions[j], positions[k]);
                  res += dis_temp1 * dis_temp2 * Math.abs(Math.sin(totalAngle)) ;
               }
               return (res/1000000.0).toFixed(4);
            }
            /*角度*/
            function Angle(p1, p2, p3) {
               let bearing21 = Bearing(p2, p1);
               let bearing23 = Bearing(p2, p3);
               let angle = bearing21 - bearing23;
               if (angle < 0) {
                  angle += 360;
               }
               return angle;
            }
            /*方向*/
            function Bearing(from, to) {
               let lat1 = from.lat * radiansPerDegree;
               let lon1 = from.lon * radiansPerDegree;
               let lat2 = to.lat * radiansPerDegree;
               let lon2 = to.lon * radiansPerDegree;
               let angle = -Math.atan2(Math.sin(lon1 - lon2) * Math.cos(lat2), Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2));
               if (angle < 0) {
                  angle += Math.PI * 2.0;
               }
               angle = angle * degreesPerRadian;//角度
               return angle;
            }
            //计算距离
            function distance(point1,point2){
               let point1cartographic = Cesium.Cartographic.fromCartesian(point1);
               let point2cartographic = Cesium.Cartographic.fromCartesian(point2);
               /**根据经纬度计算出距离**/
               let geodesic = new Cesium.EllipsoidGeodesic();
               geodesic.setEndPoints(point1cartographic, point2cartographic);
               let s = geodesic.surfaceDistance;
               //console.log(Math.sqrt(Math.pow(distance, 2) + Math.pow(endheight, 2)));
               //返回两点之间的距离
               s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
               return s;
            }
            console.log(getArea(points)+"平方公里","777")
         },
         //鼠标事件
         movehandLer: function movehandLer() {
            // 取消默认双击事件
            this.map.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
            // 获取鼠标事件
            this.mountainHandler = new Cesium.ScreenSpaceEventHandler(this.map.scene.canvas);
            // 给鼠标左键添加事件函数
            this.mountainHandler.setInputAction(lang.hitch(this, this.clickHand), Cesium.ScreenSpaceEventType.LEFT_CLICK);
         },
         //点击事件
         clickHand:function (click){
            var pickedObjects = this.map.scene.pick(click.position);
            if (pickedObjects.primitive instanceof Cesium.Primitive) {
               this.canvasToImage()
               this.floodAnalysisPopup()
            }
         },
         //洪水分析弹窗
         floodAnalysisPopup:function (){
            var url = './corelib/common/popup/floodAnalysis.html';
            var top = ($(window).height() - 600) / 2;
            var left = ($(window).width() - 900 - 340) / 2 + 340;
            var self = this
            for (let i = 0; i < this.peoplePositionArray.length; i++) {
               let inPolygon = this.isPointInPolygon(this.peoplePositionArray[i])
               this.peoplePositionArray[i].inPolygon = inPolygon
            }
            layer.open({
               title:'模拟分析',
               type: 2,
               maxmin: false, //开启最大化最小化按钮
               area: ['1100px', '600px'],
               skin: 'floodAnalysis',
               offset: [top, left],
               content: url,
               id: "floodAnalysisLayer",
               closeBtn: 1,
               //把父页面数据传递给子弹窗并渲染
               success: function(layero, index) {
                  var body = layer.getChildFrame("body",index);//绑定父子之间的关系,用于数据传递,缺少则无法传递
                  var iframeWin = window[layero.find('iframe')[0]['name']];//得到iframe页的窗口对象
                  iframeWin.$('#canvasImage')[0].src = self.canvasImage; //渲染子页面中的img
               },
            });
         },
         //添加点
         addPoint:function (){
            const url = './widgets/FloodAnalysis/data.json'
            this.getJsonUrl(url)
         },
         //判断点是否在多边形内部
         isPointInPolygon : function (point){
            //获取经纬度
            var polygonPosition = this.getPositionArray(this.polygonCartesianArray)
            //turf要求首尾闭合
            var turfPolygon = []
            polygonPosition.forEach(e=>{
               var temp = [e.lon,e.lat]
               turfPolygon.push(temp)
            })
            turfPolygon.push([polygonPosition[0].lon,polygonPosition[0].lat])
            var poly= turf.polygon([turfPolygon])
            var pt = turf.point([point.LGTD,point.LTTD])
            return turf.booleanPointInPolygon(pt,poly)
         },
         //获取json对象,测试用
         getJsonUrl: function getJsonUrl(url) {
            var self = this;
            $.ajax({
               url: url,
               dataType: 'json',
               type: 'get',
               success: function success(data) {
                  const viewer = self.map
                  var dataArray = data.data
                  self.peoplePositionArray = dataArray
                  for (let i = 0; i < dataArray.length; i++) {
                     var temp = viewer.entities.add({
                        position: Cesium.Cartesian3.fromDegrees(dataArray[i].LGTD, dataArray[i].LTTD),
                        point: {
                           color: Cesium.Color.RED,
                           pixelSize: 16,
                           //防止地形遮挡住点
                           disableDepthTestDistance: Number.POSITIVE_INFINITY
                        },
                     });
                  }
               }
            });
         },
         //canvas转换为image
         canvasToImage:function (){
            var canvas = this.map.scene.canvas
            let image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
            this.canvasImage = image
            // //导出看效果
            // let link = document.createElement("a");
            // let blob = this.dataURLtoBlob(image);
            // let objurl = URL.createObjectURL(blob);
            // link.download = "scene.png";
            // link.href = objurl;
            // link.click();
         },
         dataURLtoBlob:function (dataurl) {
         let arr = dataurl.split(','),
            mime = arr[0].match(/:(.*?);/)[1],
            bstr = atob(arr[1]),
            n = bstr.length,
            u8arr = new Uint8Array(n);
         while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
         }
         return new Blob([u8arr], { type: mime });
      }
      });
   });
    });
});