赣州市洪水风险预警系统三维版本
guoshilong
2023-02-06 d41024c55f6b7515d3880457d83be99fbbcf6622
widgets/FloodAnalysis/Widget copy.js
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////
// Copyright © 2020 zhongsong. All Rights Reserved.
// 模块描述:河流水面线分析
// Copyright © 2022 guoshilong. All Rights Reserved.
// 模块描述:洪水淹没分析
///////////////////////////////////////////////////////////////////////////
define([
   'dojo/_base/declare',
@@ -10,19 +10,25 @@
   'dojo/topic',
   'jimu/BaseWidget',
   './Tooltip-div',
   './DynamicDraw'
   './FloodAnalysis',
   'libs/layer/layer.js',
   'libs/turf/turf.min.js'
],
   function (declare,
      lang,
      array,
      html,
      topic,
      BaseWidget
      BaseWidget,
      tooltip,
      flood,
      layer,
      turf,
   ) {
      return declare([BaseWidget], {
         baseClass: 'jimu-widget-DynamicRiver',
         name: 'DynamicRiver',
         riverWidth: 200,
         baseClass: 'jimu-widget-FloodAnalysis',
         name: 'FloodAnalysis',
         riverWidth: 300,
         riverHeight: 10,
         speed: 10,
         positions: [],
@@ -30,8 +36,13 @@
         riverPrimitive: null,
         material: null,
         drawingPolyline: null,
         // 增加waterData 用来存放列表数据
         waterData: null,
         //绘制的多边形数组
         polygonCartesianArray:[],
         //canvas转换后的图片
         canvasImage:null,
         //房屋人口
         peoplePositionArray:[],
         myWaterPrimitive:null,
         startup: function () {
            this.inherited(arguments);
            var self = this;
@@ -39,106 +50,82 @@
            this.map.scene.globe.depthTestAgainstTerrain = true;
            //取消双击事件
            this.map.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
            // 点击地图上绘制水面线,并且显示水面线详细数据
            $('.water-analysis-content').on('click', '.content-right', function (e) {
               var dataIndex = $(e.target).parent().index();
               var cartesians = [];
               self.map.camera.flyTo({
                  destination: Cesium.Cartesian3.fromDegrees(Number(self.waterData[dataIndex].zb[0].jd), Number(self.waterData[dataIndex].zb[0].wd), 5000),
                  easingFunction: Cesium.EasingFunction.QUADRACTIC_IN_OUT
            //绘制水面事件
            $("#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()
                  self.showDetail(true)
               });
            });
               $('.dynamicriver-result-sname').text(self.waterData[dataIndex].sname);
               $('.dynamicriver-result-ctime').text(self.waterData[dataIndex].ctime.substring(0, 10));
               $('.dynamicriver-result-ltime').text(self.waterData[dataIndex].ltime.substring(0, 10));
               if (e.target.nodeName == 'SPAN') {
                  $('.dynamicriver-result').stop().show();
                  $('.dynamicriver-main').stop().hide();
               }
               // $('.jimu-widget-DynamicRiver .dynamicriver-result').fadeIn();
               self.waterData[dataIndex].zb.forEach(function (item, index) {
                  cartesians.push(Cesium.Cartesian3.fromDegrees(item.jd, item.wd, item.elevation))
               })
               // self.drawLines(cartesians);
               // 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);
               // });
            })
            $('.close-dynamicriver').click(function () {
               $('.jimu-widget-DynamicRiver').stop().hide();
            })
            // 关闭详细信息事件
            $('.close-dynamicriver-result').click(function () {
               $('.dynamicriver-result').stop().hide();
               $('.dynamicriver-main').stop().show();
            $('#flood_qcsmx_headtab').click(function () {
               self.map.entities.remove(self.drawingPolyline);
               self.map.scene.primitives.remove(self.riverPrimitive);
               self.map.camera.flyTo({
                  destination: Cesium.Cartesian3.fromDegrees(115.257787, 25.885506, 549263.35),
                  easingFunction: Cesium.EasingFunction.QUADRACTIC_IN_OUT
               });
               self.showDetail(false)
            })
            // $("#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);
            // });
            $('#flood-detail-ksfx').click(function () {
               self.floodAnalysisPopup()
            })
            /*for(var e = [
                  [115.907543, 30.441563, 541.47],
                  [115.904337, 30.439412, 491.79],
                  [115.900612, 30.438483, 449.11],
                  [115.896375, 30.439377, 388.29],
                  [115.890586, 30.442215, 345.94],
                  [115.876946, 30.444641, 292.73]
               ], r = [], i = 0; i < e.length; i++) r.push(Cesium.Cartesian3.fromDegrees(e[i][0], e[i][1], e[i][2]));
            this.positions = r;
            this.init();*/
         },
         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);
               this.myWaterPrimitive = this.map.scene.primitives.add(this.riverPrimitive);
            }
         },
         prepareVertex: function () {
            if (this.positions.length > 0) {
               this.sideRes = this._lines2Plane(this.positions, this.riverWidth, this.riverHeight);
            }
         },
         setPositions: function (e) {
            this.positions = e;
            this.init();
         },
         resetPos: function () {
            this.sideRes = this._lines2Plane(this.positions, this.riverWidth, this.riverHeight);
            if (this.sideRes) {
@@ -148,14 +135,16 @@
               this.map.scene.primitives.add(this.riverPrimitive);
            }
         },
         drawLines: function (r) {
            this.setPositions(r);
         },
         prepareMaterial: function () {
            var e = new Cesium.Material({
               fabric: {
                  uniforms: {
                     image: "widgets/DynamicRiver/images/movingRiver.png",
                     image: "widgets/ThematicDynamicRiver/images/movingRiver.png",
                     alpha: 0.5,
                     moveVar: new Cesium.Cartesian3(50, 1, 100),
                     reflux: -1,
@@ -168,6 +157,7 @@
            });
            return e
         },
         createPrimitive: function () {
            var t = new Float64Array(this.sideRes.vertexs),
               i = new Cesium.GeometryAttributes;
@@ -201,9 +191,11 @@
               })
            })
         },
         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++) {
@@ -221,6 +213,7 @@
               }, this.map.clock.onTick.addEventListener(this.dhEvent)
            }
         },
         //水面线转成水面
         _lines2Plane: function (positions, width, height) {
            function n(point, height) {
@@ -302,6 +295,17 @@
               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)
            }
            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)
            return {
               left: v,
               right: y,
@@ -313,34 +317,29 @@
               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(0)').trigger('click');
            $($('div.cesium-viewer').find('.cesium-baseLayerPicker-choices')[1]).children('div:eq(2)').trigger('click');
            // 发送请求获得到水面线列表基本数据
            var self = this;
            $.ajax({
               url: 'http://localhost:82/blade-ycreal/waterline/querylist',
               dataType: 'json',
               type: 'get',
               success: function (data) {
                  self.waterData = data.data;
                  var lidom = null;
                  var contentLeft = null;
                  var contentRight = null;
                  for (var i = 0; i < data.data.length; i++) {
                     lidom = $('<li> </li>');
                     contentLeft = $("<span class='content-left'></span>").text(data.data[i].sname);
                     contentRight = $("<span class='content-right'></span>");
                     lidom.prepend(contentLeft);
                     lidom.append(contentRight);
                     $('.water-analysis-content').append(lidom);
                  }
               }
            })
            this.map.camera.setView({
               destination: Cesium.Cartesian3.fromDegrees(116.016905,25.884684, 10000),
            });
            this.showDetail(false)
         },
         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 () {
@@ -360,7 +359,269 @@
            //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 && pickedObjects.primitive instanceof Cesium.Primitive) {
               // this.canvasToImage()
               this.floodAnalysisPopup()
            }
         },
         //洪水分析弹窗
         floodAnalysisPopup:function (){
            var self = this
            var inPolygon = []
            for (let i = 0; i < this.peoplePositionArray.length; i++) {
               let isIn = this.isPointInPolygon(this.peoplePositionArray[i])
               if (isIn){
                  inPolygon.push(this.peoplePositionArray[i])
               }
            }
            var jsonStr = JSON.stringify(inPolygon)
            var url = './corelib/common/popup/floodAnalysis.html';
            var urlEvaluate = './corelib/common/popup/evaluateAnalysis.html'
            var top = ($(window).height() - 600) / 2;
            var left = ($(window).width() - 1300 - 340) / 2 + 340;
            layer.open({
               title:'评估分析',
               type: 2,
               maxmin: false, //开启最大化最小化按钮
               area: ['1100px', '600px'],
               skin: 'floodAnalysis',
               offset: [top, left],
               content: urlEvaluate + "?data=" + encodeURIComponent(jsonStr),//使用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']];
                  // //渲染子页面中的img
                  // iframeWin.$('#canvasImage')[0].src = self.canvasImage;
                  var table = ""
                  var house = 0
                  var people = 0
                  var area = 0
                  var money = 0
                  for (let i = 0; i < inPolygon.length; i++) {
                     table += '<tr>'+
                        '<td><div>' + inPolygon[i].name + '</div></td>' +
                        '<td><div>' + inPolygon[i].house + '</div></td>' +
                        '<td><div>' + inPolygon[i].people + '</div></td>' +
                        '<td><div>' + inPolygon[i].area + '</div></td>' +
                        '<td><div>' + inPolygon[i].money + '</div></td>' +
                        '</tr>'
                     house += inPolygon[i].house
                     people += inPolygon[i].people
                     area += inPolygon[i].area
                     money += inPolygon[i].money
                  }
                  iframeWin.$('#evaluate-tbody').html(table)
                  iframeWin.$(".house").html(house + '户')
                  iframeWin.$(".people").html(people + '人')
                  iframeWin.$(".area").html(area + 'km²')
                  iframeWin.$(".money").html(money + '万元')
               },
            });
         },
         //添加点
         addPoint:function (){
            const url = './widgets/FloodAnalysis/data.json'
            this.getJsonUrl(url)
         },
         showDetail:function(show){
            //显示详情
            if (show){
               $('.flood-detail').show()
            }else {
               $('.flood-detail').hide()
            }
         },
         //判断点是否在多边形内部
         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
                  dataArray.forEach(e=>{
                     e.house = Number(e.house)
                     e.people = Number(e.people)
                     e.area = Number(e.area)
                     e.money = Number(e.money)
                  })
                  self.peoplePositionArray = []
                  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 });
      },
      });
   });