| | |
| | | /////////////////////////////////////////////////////////////////////////// |
| | | // Copyright © 2020 zhongsong. All Rights Reserved. |
| | | // 模块描述:河流水面线分析 |
| | | // Copyright © 2022 guoshilong. All Rights Reserved. |
| | | // 模块描述:洪水淹没分析 |
| | | /////////////////////////////////////////////////////////////////////////// |
| | | define([ |
| | | 'dojo/_base/declare', |
| | |
| | | '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: [], |
| | |
| | | riverPrimitive: null, |
| | | material: null, |
| | | drawingPolyline: null, |
| | | // 增加waterData 用来存放列表数据 |
| | | waterData: null, |
| | | //绘制的多边形数组 |
| | | polygonCartesianArray:[], |
| | | //canvas转换后的图片 |
| | | canvasImage:null, |
| | | //房屋人口 |
| | | peoplePositionArray:[], |
| | | myWaterPrimitive:null, |
| | | startup: function () { |
| | | this.inherited(arguments); |
| | | var self = this; |
| | |
| | | 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) { |
| | |
| | | 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, |
| | |
| | | }); |
| | | return e |
| | | }, |
| | | |
| | | createPrimitive: function () { |
| | | var t = new Float64Array(this.sideRes.vertexs), |
| | | i = new Cesium.GeometryAttributes; |
| | |
| | | }) |
| | | }) |
| | | }, |
| | | |
| | | 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++) { |
| | |
| | | }, this.map.clock.onTick.addEventListener(this.dhEvent) |
| | | } |
| | | }, |
| | | |
| | | //水面线转成水面 |
| | | _lines2Plane: function (positions, width, height) { |
| | | function n(point, height) { |
| | |
| | | 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, |
| | |
| | | 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 () { |
| | |
| | | //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 }); |
| | | }, |
| | | |
| | | |
| | | }); |
| | | }); |