src/main/java/com/moral/controller/ScreenController.java
@@ -1,16 +1,11 @@ package com.moral.controller; import static com.moral.common.util.ResourceUtil.getValue; import static com.moral.common.util.WebUtils.getParametersStartingWith; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.text.DecimalFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Month; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; @@ -21,9 +16,6 @@ import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.net.ftp.FTPClient; @@ -98,11 +90,15 @@ import com.moral.service.WeatherService; import com.moral.util.AQICalculation; import com.moral.util.TempAllocationUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import static com.moral.common.util.ResourceUtil.getValue; import static com.moral.common.util.WebUtils.getParametersStartingWith; /** * The Class ScreenController.大屏接口 @@ -1225,7 +1221,7 @@ @GetMapping("/pollutionSource") @ApiOperation(value = "污染传播来源", notes = "污染传播来源") @ApiImplicitParams(value = { @ApiImplicitParam(name = "mac", value = "设备mac地址(如:898607b0101730392254)", required = true, paramType = "query", dataType = "String"), @ApiImplicitParam(name = "mac", value = "设备mac地址(如:898607b0101730392251)", required = true, paramType = "query", dataType = "String"), @ApiImplicitParam(name = "sensorKey", value = "查询的监测因子的key(格式:e1)", required = true, paramType = "query", dataType = "String"), @ApiImplicitParam(name = "time", value = "查询时间(格式:2019-09-01-10)", required = true, paramType = "query", dataType = "String")}) public ModelAndView pollutionSource(ModelAndView model, HttpServletRequest request) throws Exception { @@ -1238,17 +1234,17 @@ LocalDateTime timeLocalDateTime = LocalDateTime.parse(time, dateTimeFormatter); System.out.println(timeLocalDateTime); int month = timeLocalDateTime.getMonth().getValue(); Point dirPoint= historyHourlyService.getDirPoint(parameters); Map<String,Object> getPollutionSourceData=historyHourlyService.getPollutionSourceData(parameters); Point dirPoint = historyHourlyService.getDirPoint(parameters); Map<String, Object> getPollutionSourceData = historyHourlyService.getPollutionSourceData(parameters); System.out.println(dirPoint.toString()); System.out.println("getPollutionSourceData:"+getPollutionSourceData); System.out.println("getPollutionSourceData:" + getPollutionSourceData); String mac = parameters.get("mac").toString(); Device device = deviceService.getDeviceByMac(mac, false); JSONObject params = new JSONObject(); params.put("device", device); params.put("month", month); params.put("dirPoint",dirPoint); params.put("getPollutionSourceData",getPollutionSourceData); params.put("dirPoint", dirPoint); params.put("getPollutionSourceData", getPollutionSourceData); String paramsJson = params.toJSONString(); model.addObject("pollutionSourceParams", paramsJson); model.setViewName("pollutionsource"); src/main/java/com/moral/service/impl/HistoryHourlyServiceImpl.java
@@ -5,8 +5,6 @@ import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.apache.commons.collections.MapUtils; import org.springframework.stereotype.Service; @@ -17,6 +15,7 @@ import com.moral.mapper.SensorMapper; import com.moral.service.DeviceService; import com.moral.service.HistoryHourlyService; import javax.annotation.Resource; @Service public class HistoryHourlyServiceImpl implements HistoryHourlyService { @@ -37,31 +36,23 @@ sensorKeys.add(sensor.getSensorKey()); } parameters.put("sensorKeys", sensorKeys); /* if(pollutionSourceData.get("e6")!=null&&pollutionSourceData.get("e18")!=null){ pollutionSourceData=historyHourlyMapper.getPollutionSourceData(parameters); } return pollutionSourceData;*/ System.out.println("----"+historyHourlyMapper.getPollutionSourceData(parameters)); return historyHourlyMapper.getPollutionSourceData(parameters); return historyHourlyMapper.getPollutionSourceData(parameters); } @Override public Point getDirPoint(Map<String, Object> parameters) throws Exception{ Map<String,Object> pollutionSourceData=getPollutionSourceData(parameters); public Point getDirPoint(Map<String, Object> parameters) throws Exception { Map<String, Object> pollutionSourceData = getPollutionSourceData(parameters); String mac = parameters.get("mac").toString(); Device device = deviceService.getDeviceByMac(mac, false); Point pointEnd=new Point(); if(MapUtils.isNotEmpty(pollutionSourceData)){ System.out.println("pollutionSourceData"+pollutionSourceData); if(pollutionSourceData.get("e18")!=null&&pollutionSourceData.get("e23")!=null&&pollutionSourceData.get("e6")!=null){ double windSpeed=Double.valueOf(pollutionSourceData.get("e18").toString()); double winDir=Double.valueOf(pollutionSourceData.get("e23").toString()); double distance=windSpeed*3600; double long1=device.getLongitude(); double lat1=device.getLatitude(); System.out.println("windSpeed:"+windSpeed+"---winDir:"+winDir+"---distance:"+distance+"--long1:"+long1+"--lat1:"+lat1); String[] result=calLocationByDistanceAndLocationAndDirection(winDir,long1,lat1,distance); System.out.println("result1:"+Double.valueOf(result[0])+"result2:"+Double.valueOf(result[1])); Point pointEnd = new Point(); if (MapUtils.isNotEmpty(pollutionSourceData)) { if (pollutionSourceData.get("e18") != null && pollutionSourceData.get("e23") != null && pollutionSourceData.get("e6") != null) { double windSpeed = Double.valueOf(pollutionSourceData.get("e18").toString()); double winDir = Double.valueOf(pollutionSourceData.get("e23").toString()); double distance = windSpeed * 3600; double long1 = device.getLongitude(); double lat1 = device.getLatitude(); String[] result = calLocationByDistanceAndLocationAndDirection(winDir, long1, lat1, distance); pointEnd.setLng(Double.valueOf(result[0])); pointEnd.setLat(Double.valueOf(result[1])); } @@ -70,29 +61,29 @@ } /** * 根据一点的坐标与距离,以及方向,计算另外一点的位置 * @param angle 角度,从正北顺时针方向开始计算 * * @param angle 角度,从正北顺时针方向开始计算 * @param startLong 起始点经度 * @param startLat 起始点纬度 * @param distance 距离,单位m * @param startLat 起始点纬度 * @param distance 距离,单位m * @return */ private String[] calLocationByDistanceAndLocationAndDirection(double angle, double startLong,double startLat, double distance){ private String[] calLocationByDistanceAndLocationAndDirection(double angle, double startLong, double startLat, double distance) { /** 地球半径 **/ final double R = 6371e3; /** 180° **/ final DecimalFormat df = new DecimalFormat("0.000000"); String[] result = new String[2]; //将距离转换成经度的计算公式 double δ = distance/R; double δ = distance / R; // 转换为radian,否则结果会不正确 angle = Math.toRadians(angle); startLong = Math.toRadians(startLong); startLat = Math.toRadians(startLat); double lat = Math.asin(Math.sin(startLat)*Math.cos(δ)+Math.cos(startLat)*Math.sin(δ)*Math.cos(angle)); double lng = startLong + Math.atan2(Math.sin(angle)*Math.sin(δ)*Math.cos(startLat),Math.cos(δ)-Math.sin(startLat)*Math.sin(lat)); double lat = Math.asin(Math.sin(startLat) * Math.cos(δ) + Math.cos(startLat) * Math.sin(δ) * Math.cos(angle)); double lng = startLong + Math.atan2(Math.sin(angle) * Math.sin(δ) * Math.cos(startLat), Math.cos(δ) - Math.sin(startLat) * Math.sin(lat)); // 转为正常的10进制经纬度 lng = Math.toDegrees(lng); lat = Math.toDegrees(lat); src/main/java/com/moral/service/impl/HistoryMinutelyServiceImpl.java
@@ -1,11 +1,7 @@ package com.moral.service.impl; import static com.moral.common.bean.Constants.NULL_VALUE; import static org.springframework.util.ObjectUtils.isEmpty; import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -31,8 +27,6 @@ import java.util.concurrent.Executors; import java.util.stream.Collectors; import javax.annotation.Resource; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.time.DateUtils; import org.springframework.stereotype.Service; @@ -55,6 +49,10 @@ import com.moral.mapper.HistoryMinutelyMapper; import com.moral.mapper.SensorMapper; import com.moral.service.HistoryMinutelyService; import javax.annotation.Resource; import static com.moral.common.bean.Constants.NULL_VALUE; import static org.springframework.util.ObjectUtils.isEmpty; @Service @SuppressWarnings({"unchecked", "unused", "rawtypes"}) src/main/webapp/view/pollutionsource.jsp
@@ -120,10 +120,9 @@ var params = $.parseJSON($("#pollutionSourceParams").html()); var month = params["month"]; var device = params["device"]; var dirPoint=params["dirPoint"]; console.log(dirPoint.lng); console.log(dirPoint.lat); var getPollutionSourceData=params["getPollutionSourceData"]; var dirPoint = new BMap.Point(params["dirPoint"].lng, params["dirPoint"].lat); var getPollutionSourceData = params["getPollutionSourceData"]; var windSpeed = parseFloat(getPollutionSourceData["e18"]); var map = new BMap.Map("mapCanvas", {enableMapClick: false}); map.setMapStyle(mapStyle); map.enableScrollWheelZoom(true); // 开启鼠标滚轮缩放 @@ -133,74 +132,86 @@ }); map.addControl(navigation); map.addControl(new BMap.ScaleControl()); if ($.isEmptyObject(dirPoint)||$.isEmptyObject(getPollutionSourceData)||getPollutionSourceData["e18"]==0) { if ($.isEmptyObject(dirPoint) || $.isEmptyObject(getPollutionSourceData) || getPollutionSourceData["e6"] == 0 || getPollutionSourceData["e18"] == 0 || getPollutionSourceData["e23"] == 0 || windSpeed <= 0.03) { showNoData(); }else{ var humidity=getPollutionSourceData["e6"]; var windSpeed=getPollutionSourceData["e18"]; } else { var humidity = parseFloat(getPollutionSourceData["e6"]); var windDir = parseFloat(getPollutionSourceData["e23"]); var longitude = params["device"]["longitude"]; var latitude = params["device"]["latitude"]; var point = new BMap.Point(longitude, latitude); var icon = new BMap.Icon("/img/ico00.png", new BMap.Size(50, 50)); var marker = new BMap.Marker(point, {icon: icon, offset: new BMap.Size(0, -20)}); map.addOverlay(marker); map.centerAndZoom(point, 17); var polyline1 = new BMap.Polyline([ dirPoint, new BMap.Point(point.lng+0.01, point.lat+0.01) ], {strokeColor: "#5298FF", strokeWeight: 4, strokeOpacity: 1} ); var polyline2 = new BMap.Polyline([ dirPoint, new BMap.Point( point.lng-0.02, point.lat-0.01) ], {strokeColor: "#5298FF", strokeWeight: 4, strokeOpacity: 1} ); var distance=windSpeed*3600; console.log(distance); var arrowLength;//两点间箭头长度 if (distance <= 5) { arrowLength = 0; } else if (distance > 5 && distance <= 20) { arrowLength = 2; } else if (distance > 20 && distance <= 50) { arrowLength = 3; } else if (distance > 50 && distance <= 100) { arrowLength = 5; } else if (distance > 100 && distance <= 200) { arrowLength = 10; } else if (distance > 200 && distance <= 500) { arrowLength = 20; } else if (distance > 500 && distance <= 1000) { arrowLength = 40; } else if (distance > 1000 && distance <= 2000) { arrowLength = 80; } else if (distance > 2000 && distance <= 3000) { arrowLength = 120; } else if (distance > 3000 && distance <= 10000) { arrowLength = 500; } else if (distance > 10000 && distance <= 20000) { arrowLength = 1000; } else if (distance > 20000 && distance <= 50000) { arrowLength = 2500; } else if (distance > 50000 && distance <= 100000) { arrowLength = 5000; } else if (distance > 100000 && distance <= 200000) { arrowLength = 10000; } else if (distance > 200000 && distance <= 500000) { arrowLength = 25000; } else if (distance > 500000 && distance <= 1000000) { arrowLength = 50000; } else if (distance > 1000000 && distance <= 2000000) { arrowLength = 100000; } else { arrowLength = 150000; map.centerAndZoom(point, 16); //centre:椭圆中心点,X:横向经度,Y:纵向纬度 function add_oval(centre, x, y) { var assemble = new Array(); var angle; var dot; var tangent = x / y; for (i = 0; i < 36; i++) { angle = (2 * Math.PI / 36) * i; dot = new BMap.Point(centre.lng + Math.sin(angle) * y * tangent, centre.lat + Math.cos(angle) * y); assemble.push(dot); } return assemble; } map.addOverlay(polyline1);// 画两点间线 addArrow(polyline1, arrowLength, Math.PI / 7,windSpeed); map.addOverlay(polyline2);// 画两点间线 addArrow(polyline2, arrowLength, Math.PI / 7,windSpeed); //以画多边形区域的方法画扇形区域 画出以point点为圆心,半径为radius,夹角从sDegree到eDegree的扇形 function Sector(point, radius, sDegree, eDegree) { var points = []; //创建构成多边形的点数组 var step = ((eDegree - sDegree) / 10) || 10; //根据扇形的总夹角确定每步夹角度数,最大为10 points.push(point); for (var i = sDegree; i < eDegree + 0.001; i += step) { //循环获取每步的圆弧上点的坐标,存入点数组 points.push(EOffsetBearing(point, radius, i)); } points.push(point); return points; } //使用数学的方法计算需要画扇形的圆弧上的点坐标 function EOffsetBearing(point, dist, bearing) { var lngConv = map.getDistance(point, new BMap.Point(point.lng + 0.1, point.lat)) * 10; //计算经度与原点的距离 var latConv = map.getDistance(point, new BMap.Point(point.lng, point.lat + 0.1)) * 10; //计算纬度与原点的距离 var lat = dist * Math.sin(bearing * Math.PI / 180) / latConv; //正弦计算待获取的点的纬度与原点纬度差 var lng = dist * Math.cos(bearing * Math.PI / 180) / lngConv; //余弦计算待获取的点的经度与原点经度差 return new BMap.Point(point.lng + lng, point.lat + lat); } var distance = windSpeed * 3600; var winDirStart = 240 - windDir; var winDirEnd = 300 - windDir; var oval = new BMap.Polygon(Sector(dirPoint, distance, winDirStart, winDirEnd), { strokeColor: "grey", strokeWeight: 1, strokeOpacity: 0.8, fillColor: "grey" }); map.addOverlay(oval); var oval = new BMap.Polygon(Sector(dirPoint, distance * 0.66, winDirStart, winDirEnd), { strokeColor: "grey", strokeWeight: 1, strokeOpacity: 0.6, fillColor: "grey" }); map.addOverlay(oval); var oval = new BMap.Polygon(Sector(dirPoint, distance * 0.33, winDirStart, winDirEnd), { strokeColor: "grey", strokeWeight: 1, strokeOpacity: 0.4, fillColor: "grey" }); map.addOverlay(oval); var polyline = new BMap.Polyline([ dirPoint, point ], {strokeColor: "#5298FF", strokeWeight: 4, strokeOpacity: 1} ); addArrow(polyline, 0, Math.PI / 7, windSpeed, humidity); var winfowTextCause = "<p style='height: 44px;line-height: 22px'>汽车尾气,工厂废气,以及周边地区农田秸秆焚烧,污染传播途径是根据风向来做出调整</p>"; var winfowTextSource; var supplement; @@ -208,40 +219,40 @@ if (windSpeed >= 3.4) { supplement = ",但风速较大,大气扩散条件较有利,空气质量相对提升"; } if (humidity>=90.0) { if (humidity >= 90.0) { supplement = ",但降雨有利于对颗粒物的沉降、冲刷,改善污染状况"; }else{ supplement =""; } else { supplement = ""; } winfowTextSource = "<p style='height: 22px;line-height: 22px'>压强升高气温降低,会因冷空气带来的颗粒物,导致污染上升" + supplement + "</p>"; } else if (month == 3 || month == 4 || month == 5) { if (windSpeed >= 3.4) { supplement = ",但风速较大,大气扩散条件较有利,空气质量相对提升"; } if (humidity>=90.0) { if (humidity >= 90.0) { supplement = ",但降雨有利于对颗粒物的沉降、冲刷,改善污染状况"; }else{ supplement =""; } else { supplement = ""; } winfowTextSource = "<p style='height: 22px;line-height: 22px'>地面逆温频率的增加使污染物在近地层不断积累" + supplement + "</p>"; } else if (month == 6 || month == 7) { if (windSpeed >= 3.4) { supplement = ",同时风速较大,加速扩散"; } if (humidity>=90.0) { if (humidity >= 90.0) { supplement = ",同时降雨有利于对颗粒物的沉降、冲刷,改善污染状况"; }else{ supplement =""; } else { supplement = ""; } winfowTextSource = "<p style='height: 22px;line-height: 22px'>夏季的气温条件不易发生逆温,利于污染物扩散" + supplement + "</p>"; } else if (month == 8 || month == 9 || month == 10 || month == 11) { if (windSpeed >= 3.4) { supplement = ",但风速较大,利于污染物扩散"; } if (humidity>=90.0) { if (humidity >= 90.0) { supplement = ",但降雨有利于对颗粒物的沉降、冲刷,改善污染状况"; }else{ supplement =""; } else { supplement = ""; } winfowTextSource = "<p style='height: 22px;line-height: 22px'>大气扩散条件不好使污染物聚集,增大了气态污染物向二次颗粒物转化的机会" + supplement + "</p>"; } @@ -263,9 +274,7 @@ }); } function addArrow(polyline, length, angleValue,windSpeed) { function addArrow(polyline, length, angleValue, windSpeed, humidity) { var linePoint = polyline.getPath();// 线的坐标串 var arrowCount = linePoint.length; for (var i = 1; i < arrowCount; i++) { // 在拐点处绘制箭头 @@ -276,7 +285,7 @@ var delta = 0; // 主线斜率,垂直时无斜率 var param = 0; // 代码简洁考虑 var pixelTemX, pixelTemY, poMiddleX, poMiddleY;// 临时点坐标 var pixelX, pixelY, pixelX1, pixelY1;// 箭头两个点 var pixelX, pixelY;// 箭头两个点 poMiddleX = (pixelEnd.x + pixelStart.x) / 2; poMiddleY = (pixelEnd.y + pixelStart.y) / 2; if (poMiddleX - pixelStart.x == 0) { // 斜率不存在时 @@ -288,8 +297,7 @@ } // 已知直角三角形两个点坐标及其中一个角,求另外一个点坐标算法 pixelX = pixelTemX - r * Math.tan(angle); pixelX1 = pixelTemX + r * Math.tan(angle); pixelY = pixelY1 = pixelTemY; pixelY = pixelTemY; } else { // 斜率存在时 delta = (poMiddleY - pixelStart.y) / (poMiddleX - pixelStart.x); param = Math.sqrt(delta * delta + 1); @@ -303,24 +311,20 @@ // 已知直角三角形两个点坐标及其中一个角,求另外一个点坐标算法 pixelX = pixelTemX + Math.tan(angle) * r * delta / param; pixelY = pixelTemY - Math.tan(angle) * r / param; pixelX1 = pixelTemX - Math.tan(angle) * r * delta / param; pixelY1 = pixelTemY + Math.tan(angle) * r / param; } var pointArrow = map.pixelToPoint(new BMap.Pixel(pixelX, pixelY)); var pointArrow1 = map.pixelToPoint(new BMap.Pixel(pixelX1, pixelY1)); var pointMiddle = map.pixelToPoint(new BMap.Pixel(poMiddleX, poMiddleY)); lab = new BMap.Label("风速:"+windSpeed+"m/s", {position: pointMiddle, offset: new BMap.Size(0, -30)}); lab = new BMap.Label("<P>风速:" + windSpeed + "m/s</p><P>湿度:" + humidity + "°</p>", { position: pointMiddle, offset: new BMap.Size(-50, -20) }); lab.setStyle({ color: "red", color: "#FFFFFF", fontSize: "16px", backgroundColor: "1", border: "0", fontWeight: "bold" }); map.addOverlay(lab); var Arrow = new BMap.Polyline([pointArrow, pointMiddle, pointArrow1], {strokeColor: "#5298FF", strokeWeight: 4, strokeOpacity: 1}); map.addOverlay(Arrow); } }; @@ -333,4 +337,5 @@ document.getElementById("cpm").style.display = 'block'; }, 250); }; </script>