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))
|
// }
|
// }
|
}
|
}
|
}
|
}
|
}
|