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