feiyu02
2025-10-21 eb3dd00b0b7fcda477229d518d250f9c842b790b
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
package com.flightfeather.uav.biz.report
 
import com.flightfeather.uav.common.net.AMapService
import com.flightfeather.uav.common.utils.MapUtil
import com.flightfeather.uav.domain.entity.GridCell
import com.flightfeather.uav.domain.entity.SceneInfo
import com.flightfeather.uav.domain.entity.getByFactorType
import com.flightfeather.uav.domain.repository.SceneInfoRep
import com.flightfeather.uav.lightshare.bean.GridDataDetailMixVo
import com.flightfeather.uav.lightshare.eunm.PollutionDegree
import com.flightfeather.uav.lightshare.eunm.SceneType
import com.flightfeather.uav.socket.eunm.FactorType
 
/**
 * 走航网格叠加
 * @date 2025/9/4
 * @author feiyu02
 */
class MissionGridFusion(private val sceneInfoRep: SceneInfoRep) {
 
    companion object {
        // 需统计高风险网格的数量
        const val HIGH_RISK_GRID_NUM = 3
    }
 
    /**
     * 按AQI等级叠加网格
     */
    class GridFusionByAQI {
        var pollutionDegree: String? = null
        var gridLen:Int? = null
        var missionList: MutableList<MissionInventory.MissionInfo> = mutableListOf()
        var gridFusionList: MutableList<FusionGrid> = mutableListOf()
        var highRiskGridList: MutableList<HighRiskGridByFactor> = mutableListOf()
        // 走航区域内的高风险网格
        var highRiskGridMap: MutableMap<FactorType, List<HighRiskGridByFactor>> = mutableMapOf()
        // 报告对应的辖区内的高风险网格
        var highRiskGridMap2: MutableMap<FactorType, List<HighRiskGridByFactor>> = mutableMapOf()
    }
 
    /**
     * 叠加网格
     */
    class FusionGrid(
        val cell: GridCell,
        val data: GridDataDetailMixVo,
    )
 
    /**
     * 监测因子的高风险叠加网格
     */
    class HighRiskGridByFactor{
        // 因子类型
        var factorType: FactorType? = null
        // 高风险网格信息
        var highRiskGrid: FusionGrid? = null
        // 因子值
        var factorValue: Float? = null
        // 涉及的街镇
        var town: String? = null
        // 四至范围,顺序为最小经度,最大经度, 最小纬度,最大纬度
        var bounds: List<Double>? = null
        // 高风险场景列表
        var highRiskScenes:List<SceneInfo?>? = null
    }
 
    /**
     * 生成网格融合数据,按AQI等级分组并计算各监测因子的高风险区域
     *
     * @param factorTypes 需要分析的监测因子类型列表
     * @param gridLen 网格边长(米)
     * @param gridCells 网格单元列表,包含网格的地理信息和索引
     * @param dataList 三元组列表,每个元素包含:
     *                 - 污染等级(PollutionDegree)
     *                 - 走航任务详情列表(MissionDetail)
     *                 - 网格数据详情列表(GridDataDetailMixVo)
     * @return 按AQI等级分组的网格融合结果列表,每个元素包含该等级下的所有网格数据和高风险分析
     */
    fun generateGridFusion(
        factorTypes: List<FactorType>,
        gridLen: Int,
        gridCells: List<GridCell>,
        dataList: List<Triple<PollutionDegree, List<MissionInventory.MissionInfo>, List<GridDataDetailMixVo>>>,
    ): List<GridFusionByAQI> {
        val polyLineJingAn = AMapService.polyLineJingAn.split(";")
            .map {
                val p = it.split(",")
                Pair(p[0].toDouble(), p[1].toDouble())
            }
 
        return dataList.map {
            GridFusionByAQI().apply {
                // 空气质量等级
                pollutionDegree = it.first.des
                // 网格边长(米)
                this.gridLen = gridLen
                // 走航任务详情列表
                missionList.addAll(it.second)
                // 网格融合列表
                gridFusionList.addAll(it.third.map { gdm ->
                    val grid = gridCells.find { it.cellIndex == gdm.cellId }
                        ?: throw IllegalArgumentException("网格组${gdm.groupId}中,单元ID: ${gdm.cellId} 不存在")
                    FusionGrid(grid, gdm)
                })
                // 监测因子的高风险叠加网格列表(每种因子取均值最高的网格)(2025.10.17 取消此逻辑)
//                highRiskGridList.addAll(factorTypes.map { f->
//                    HighRiskGridByFactor().apply {
//                        factorType = f
//                        highRiskGrid = gridFusionList.maxByOrNull { gf->gf.data.getByFactorType(f) ?: 0f }
//                        if (highRiskGrid != null) {
//                            factorValue = highRiskGrid!!.data.getByFactorType(f)
//                            if (highRiskGrid!!.cell.longitude != null && highRiskGrid!!.cell.latitude != null) {
//                                Thread.sleep(100)
//                                val address = AMapService.reGeo(MapUtil.wgs84ToGcj02(
//                                    highRiskGrid!!.cell.longitude.toDouble()
//                                            to highRiskGrid!!.cell.latitude.toDouble()
//                                ))
//                                town = address.township + address.address
//                            }
//                            val polygon = listOf(
//                                highRiskGrid!!.cell.point1Lon.toDouble() to highRiskGrid!!.cell.point1Lat.toDouble(),
//                                highRiskGrid!!.cell.point2Lon.toDouble() to highRiskGrid!!.cell.point2Lat.toDouble(),
//                                highRiskGrid!!.cell.point3Lon.toDouble() to highRiskGrid!!.cell.point3Lat.toDouble(),
//                                highRiskGrid!!.cell.point4Lon.toDouble() to highRiskGrid!!.cell.point4Lat.toDouble(),
//                            )
//                            bounds = MapUtil.calFourBoundaries(polygon)
//                            highRiskScenes = sceneInfoRep.findByPolygon(polygon)
//                        }
//                    }
//                })
                // 监测因子的高风险叠加网格列表(每种因子取均值最高的3个网格)(2025.10.17 新增此逻辑)
                factorTypes.forEach { f->
                    gridFusionList.sortByDescending { gf->gf.data.getByFactorType(f) ?: 0f }
                    val takeList = mutableListOf<HighRiskGridByFactor>()
                    val takeList2 = mutableListOf<HighRiskGridByFactor>()
                    for (i in gridFusionList.indices) {
                        val gf = gridFusionList[i]
                        var highRiskGridByFactor: HighRiskGridByFactor? = null
                        if (takeList2.size < HIGH_RISK_GRID_NUM) {
                            highRiskGridByFactor = HighRiskGridByFactor().apply {
                                factorType = f
                                highRiskGrid = gf
                                factorValue = gf.data.getByFactorType(f)
                                if (gf.cell.longitude != null && gf.cell.latitude != null) {
                                    Thread.sleep(500)
                                    val address = AMapService.reGeo(MapUtil.wgs84ToGcj02(
                                        gf.cell.longitude.toDouble() to gf.cell.latitude.toDouble()
                                    ))
                                    town = if (address.address.contains(address.streetNumber)) {
                                        address.address
                                    } else {
                                        address.address + "(" + address.street + address.streetNumber + ")"
                                    }
                                }
                                val polygon = listOf(
                                    gf.cell.point1Lon.toDouble() to gf.cell.point1Lat.toDouble(),
                                    gf.cell.point2Lon.toDouble() to gf.cell.point2Lat.toDouble(),
                                    gf.cell.point3Lon.toDouble() to gf.cell.point3Lat.toDouble(),
                                    gf.cell.point4Lon.toDouble() to gf.cell.point4Lat.toDouble(),
                                )
                                bounds = MapUtil.calFourBoundaries(polygon)
                                highRiskScenes =
                                    sceneInfoRep.findByPolygon(polygon, listOf(SceneType.TYPE19, SceneType.TYPE20, SceneType.TYPE21))
                            }
                            takeList2.add(highRiskGridByFactor)
                        }
                        //
                        if (takeList.size >= HIGH_RISK_GRID_NUM) break
 
                        // fixme 2025.10.20 临时添加筛选在静安区内部的网格
                        val check = if (it.second[0].districtCode == "310106") {
                            MapUtil.isPointInPolygon(
                                    Pair(gf.cell.longitude.toDouble(), gf.cell.latitude.toDouble()),
                                    polyLineJingAn
                                )
                        } else {
                            true
                        }
                        if (check) {
                            takeList.add(highRiskGridByFactor ?: HighRiskGridByFactor().apply {
                                factorType = f
                                highRiskGrid = gf
                                factorValue = gf.data.getByFactorType(f)
                                if (gf.cell.longitude != null && gf.cell.latitude != null) {
                                    Thread.sleep(100)
                                    val address = AMapService.reGeo(MapUtil.wgs84ToGcj02(
                                        gf.cell.longitude.toDouble() to gf.cell.latitude.toDouble()
                                    ))
                                    town = if (address.address.contains(address.streetNumber)) {
                                        address.address
                                    } else {
                                        address.address + address.street + address.streetNumber
                                    }
                                }
                                val polygon = listOf(
                                    gf.cell.point1Lon.toDouble() to gf.cell.point1Lat.toDouble(),
                                    gf.cell.point2Lon.toDouble() to gf.cell.point2Lat.toDouble(),
                                    gf.cell.point3Lon.toDouble() to gf.cell.point3Lat.toDouble(),
                                    gf.cell.point4Lon.toDouble() to gf.cell.point4Lat.toDouble(),
                                )
                                bounds = MapUtil.calFourBoundaries(polygon)
                                highRiskScenes =
                                    sceneInfoRep.findByPolygon(polygon, listOf(SceneType.TYPE19, SceneType.TYPE20, SceneType.TYPE21))
                            })
                        }
 
                    }
                    highRiskGridMap[f] = takeList
                    highRiskGridMap2[f] = takeList2
 
//                    highRiskGridMap[f] = gridFusionList.take(HIGH_RISK_GRID_NUM).map { gf->
//                        HighRiskGridByFactor().apply {
//                            factorType = f
//                            highRiskGrid = gf
//                            factorValue = gf.data.getByFactorType(f)
//                            if (gf.cell.longitude != null && gf.cell.latitude != null) {
//                                Thread.sleep(100)
//                                val address = AMapService.reGeo(MapUtil.wgs84ToGcj02(
//                                    gf.cell.longitude.toDouble() to gf.cell.latitude.toDouble()
//                                ))
//                                town = address.address + address.street + address.streetNumber
//                            }
//                            val polygon = listOf(
//                                gf.cell.point1Lon.toDouble() to gf.cell.point1Lat.toDouble(),
//                                gf.cell.point2Lon.toDouble() to gf.cell.point2Lat.toDouble(),
//                                gf.cell.point3Lon.toDouble() to gf.cell.point3Lat.toDouble(),
//                                gf.cell.point4Lon.toDouble() to gf.cell.point4Lat.toDouble(),
//                            )
//                            bounds = MapUtil.calFourBoundaries(polygon)
//                            highRiskScenes =
//                                sceneInfoRep.findByPolygon(polygon, listOf(SceneType.TYPE19, SceneType.TYPE20, SceneType.TYPE21))
//                        }
//                    }
                }
            }
        }
    }
}