feiyu02
2021-12-16 49832a5bba94c816e83e7e74095106643f0a433e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package com.flightfeather.uav.lightshare.service.impl
 
import com.flightfeather.uav.common.GridLat
import com.flightfeather.uav.common.GridLng
import com.flightfeather.uav.common.utils.MapUtil
import com.flightfeather.uav.lightshare.bean.BaseResponse
import com.flightfeather.uav.lightshare.bean.GridVo
import com.flightfeather.uav.lightshare.service.EPWModelService
import com.flightfeather.uav.lightshare.service.RealTimeDataService
import com.flightfeather.uav.model.epw.EPWGridModel
import com.flightfeather.uav.model.epw.EPWModel
import com.flightfeather.uav.socket.eunm.UWDeviceType
import org.springframework.stereotype.Service
import kotlin.math.PI
 
@Service
class EPWModelServiceImpl(
    private val realTimeDataService: RealTimeDataService,
) : EPWModelService {
 
    val epwModel = EPWGridModel()
 
    override fun getEpwModelResult(deviceCode: String, startTime: String, endTime: String, len: Double): BaseResponse<List<GridVo>> {
        if (deviceCode.length < 2) return BaseResponse(false, "设备编号格式错误")
        val type = deviceCode.substring(0, 2)
        // 确定数据源类型,区分为‘定点监测数据’和‘移动监测数据两种’
        val gridType = when (type) {
            UWDeviceType.UAV.value -> '0'
            UWDeviceType.VEHICLE.value -> '0'
            UWDeviceType.GRID.value -> '1'
            UWDeviceType.BOAT.value -> 'f'
            else -> 'f'
        }
        if (gridType == 'f') return BaseResponse(false)
 
        val points = mutableListOf<GridVo>()
        // 根据不同类型,确定不同的网格生成方式,得出网格中心点集合(网格默认采用正方形)
        // 走航监测
        if (gridType == '0') {
            // TODO: 2021/12/6 走航监测网格点生成
        }
        // 定点监测
        else if (gridType == '1') {
            // FIXME: 2021/12/6 此处为了测试暂时将站点经纬度写死,后续通过数据库配置获取
            val center = Pair(121.235813, 30.835898)
            // a.确定网格长度对应的坐标差值
            val p1 = MapUtil.getPointByLen(center, len, PI / 2)//正东方向(90°)的坐标点
            val p2 = MapUtil.getPointByLen(center, len, PI)//正南方向(180°)的坐标点
            val dx = p1.first - center.first
            val dy = center.second - p2.second
            // b.确定单边有多少个网格(规定监测点在中心网格的中点上,因此单边网格数一定为奇数)
            val totalLen = 2000 // 网格范围,边长为20千米的正方形
            val gridNum = ((totalLen / 2 / len).toInt() - 1) * 2 + 1
            // c.确定左上角网格左下和右上的两个对角点坐标
            //中心点坐标
            val g1CenterLng = center.first - (gridNum - 1) / 2 * dx//经度减小
            val g1CenterLat = center.second + (gridNum - 1) / 2 * dy//纬度增加
            //左下坐标
            val g1LB = Pair(g1CenterLng - dx / 2, g1CenterLat - dy / 2)
            //右上坐标
            val g1RT = Pair(g1CenterLng + dx / 2, g1CenterLat + dy / 2)
            // d.得出所有网格的两个对角点坐标
            for (x in 0 until gridNum) {
                for (y in 0 until gridNum) {
                    points.add(GridVo("$x-$y").apply {
                        this.lb = Pair(g1LB.first + dx * x, g1LB.second - dy * y)
                        this.rt = Pair(g1RT.first + dx * x, g1RT.second - dy * y)
                        this.ciLongitude = (lb!!.first + dx / 2).toBigDecimal()
                        this.ciLatitude = (lb!!.second + dy / 2).toBigDecimal()
                    })
                }
            }
        }
        // 计算各中心点污染风险权重结果并赋予对应影响等级
        var page = 1
        var totalPage = -1
        while (totalPage == -1 || page <= totalPage) {
            realTimeDataService.getSecondData(deviceCode, startTime, endTime, 0, page, 5000).apply {
                if (totalPage == -1) {
                    totalPage = head?.totalPage ?: 0
                }
                val dataList = data ?: emptyList()
 
                // FIXME: 2021/7/13 此处为了测试暂时将站点经纬度写死,后续通过数据库配置获取
                dataList.forEach {
                    if (it.lng == 0.0 && it.lat == 0.0) {
                        it.lng = GridLng
                        it.lat = GridLat
                    }
                }
 
                epwModel.execute(dataList, points, true)
                page++
            }
        }
        val r = epwModel.outputResult()
 
        val max = mutableMapOf<String, Double>()//记录每种监测因子的最大值
//        val min = mutableMapOf<String, Double>()//记录每种监测因子的最小值
        //为每个网格赋值权重结果并且筛选各监测因子的最大最小值
        points.forEach {
            val key = "${it.sourceName};${it.index}"
            val d = r[key]
            d?.forEach { (t, u) ->
                it.result[t] = u["综合(${t})"]?.average ?: .0
 
                //筛选最大值
                if (!max.containsKey(t)) {
                    max[t] = it.result[t]!!
                } else {
                    if (max[t]!! < it.result[t]!!) {
                        max[t] = it.result[t]!!
                    }
                }
//                //筛选最小值
//                if (!min.containsKey(t)) {
//                    min[t] = it.result[t]!!
//                } else {
//                    if (min[t]!! > it.result[t]!!) {
//                        min[t] = it.result[t]!!
//                    }
//                }
            }
        }
        // 根据最大最小值,计算每个网格的各监测因子的影响等级(0->2)(影响大->小)
        points.forEach {
            it.result.forEach{ (k, v) ->
                max[k]?.let {m ->
                    val level = when (v / m) {
                        in 0.6666..1.0 -> 0
                        in 0.3333..0.6665 -> 1
                        in .0..0.3332 -> 2
                        else -> 2
                    }
                    it.level[k] = level
                }
            }
        }
        return BaseResponse(true, data = points)
    }
}