src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridManage.kt
@@ -1,10 +1,7 @@ package com.flightfeather.uav.biz.satellite import com.flightfeather.uav.common.utils.MapUtil import com.flightfeather.uav.domain.entity.BaseRealTimeData import com.flightfeather.uav.domain.entity.GridCell import com.flightfeather.uav.domain.entity.GridData import com.flightfeather.uav.domain.entity.GridDataDetail import com.flightfeather.uav.domain.entity.* import kotlin.math.PI import kotlin.math.sqrt @@ -20,7 +17,9 @@ /** * 根据正方形网格中心点坐标,计算4个顶点坐标 * 网格中心点坐标按照从左到右、从上到下的顺序排列 * @date 2025.1.8 * @param points 网格中心坐标点数组 * @return 网格4个顶点经纬度坐标 */ fun calGridVertex(points: List<Pair<Double, Double>>): List<GridVertex> { // 网格少于2个,则无法绘制 @@ -69,10 +68,11 @@ /** * 拆分网格为细分网格,所有网格应该是相同边长的正方形 * 根据相似矩形的原理,可以分别按比例得到每个细分网格的经纬度 * @date 2025.1.17 * @param gridCellList 原始网格数组 * @param scale 拆分的系数,例如 2,表示将原有网格按边长的 1/2 拆分成 2 * 2 的4个网格 * @param groupId 细分后的网格所属的网格组id * @return * @return 细分网格 */ fun splitGrid(gridCellList: List<GridCell?>, scale: Int, groupId:Int): List<GridCell?> { if (scale <= 0) throw IllegalArgumentException("网格拆分的数量不能小于1") @@ -165,9 +165,11 @@ /** * 拆分数据,将原始卫星网格遥测数据映射到对应细分网格上 * @param subGridCellList 细分网格, 按照 * @date 2025.2.7 * @param subGridCellList 细分网格 * @param subGridData 细分网格对应的数据索引 * @param originGridDataDetailList 细分网格所属网格的原始网格数据 * @return 映射后的细分网格遥测数据 */ fun splitData( subGridCellList: List<GridCell?>, subGridData: GridData, originGridDataDetailList: List<GridDataDetail?> @@ -217,21 +219,71 @@ } /** * 数据融合 * 走航数据和卫星网格融合 * 数据融合采用均值方式统计(暂时) * @date 2025.2.7 * @param realTimeDataList 待融合的走航监测数据 * @param gridData 融合后的数据组索引 * @param gridCellList 待融合的卫星网格 * @return 融合后的网格监测数据 */ fun dataFusion(realTimeDataList:List<BaseRealTimeData>, gridData: GridData, gridCellList: List<GridCell?>) { // 遍历走航监测数据,计算每个点所在网格,并形成网格值 fun dataFusion( realTimeDataList: List<BaseRealTimeData>, gridData: GridData, gridCellList: List<GridCell?>, ): List<GridDataDetail> { // 遍历走航监测数据,计算每个点所在网格 val dataMap = mutableMapOf<GridCell, MutableList<BaseRealTimeData>>() realTimeDataList.forEach { it.longitude it.latitude gridCellList.forEach { if (it.longitude == null || it.latitude == null) return@forEach searchGirdIn(it.longitude!!.toDouble() to it.latitude!!.toDouble(), gridCellList)?.let { cell -> if (!dataMap.containsKey(cell)) { dataMap[cell] = mutableListOf() } dataMap[cell]?.add(it) } } // 统计每个网格中的均值 // Fixme 2025.2.20 暂时默认以均值方式统计,后续调整为多种方式并支持用户选择 val gridDataDetailList = mutableListOf<GridDataDetail>() dataMap.forEach { (k, v) -> val avgData = v.avg() val dataDetail = GridDataDetail().apply { dataId = gridData.id groupId = k.groupId cellId = k.cellIndex pm25 = avgData.pm25 rank } gridDataDetailList.add(dataDetail) } return gridDataDetailList } /** * 计算坐标点在哪个卫星网格内 * @date 2025.2.14 * @param point 坐标点 * @param gridCellList 卫星网格 */ fun searchGirdIn(point: Pair<Double, Double>, gridCellList: List<GridCell?>): GridCell? { for (i in gridCellList.indices) { val gridCell = gridCellList[i] ?: continue val polygon = listOf( gridCell.point1Lon.toDouble() to gridCell.point1Lat.toDouble(), gridCell.point2Lon.toDouble() to gridCell.point2Lat.toDouble(), gridCell.point3Lon.toDouble() to gridCell.point3Lat.toDouble(), gridCell.point4Lon.toDouble() to gridCell.point4Lat.toDouble(), ) if (MapUtil.isPointInPolygon(point, polygon)) { return gridCell } } return null } } src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteDataCalculateService.kt
@@ -29,4 +29,11 @@ * @param dataId 数据索引id */ fun splitData(groupId: Int, dataId:Int): List<GridDataDetail?> /** * 将走航监测数据和卫星网格进行融合计算 * @param missionCode * @param groupId */ fun dataFusion(missionCode: String, groupId: Int): List<GridDataDetail?> } src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt
@@ -6,6 +6,8 @@ import com.flightfeather.uav.domain.entity.GridData import com.flightfeather.uav.domain.entity.GridDataDetail import com.flightfeather.uav.domain.entity.GridGroup import com.flightfeather.uav.domain.repository.MissionRep import com.flightfeather.uav.domain.repository.RealTimeDataRep import com.flightfeather.uav.domain.repository.SatelliteGridRep import com.flightfeather.uav.lightshare.eunm.GridType import com.flightfeather.uav.lightshare.eunm.SatelliteDataType @@ -22,7 +24,11 @@ * @author feiyu02 */ @Service class SatelliteDataCalculateServiceImpl(private val satelliteGridRep: SatelliteGridRep) : SatelliteDataCalculateService { class SatelliteDataCalculateServiceImpl( private val satelliteGridRep: SatelliteGridRep, private val realTimeDataRep: RealTimeDataRep, private val missionRep: MissionRep, ) : SatelliteDataCalculateService { override fun calGridVertex(groupId: Int): List<GridCell?> { @@ -125,4 +131,28 @@ return subGridDataDetailList } @Transactional override fun dataFusion(missionCode: String, groupId: Int): List<GridDataDetail?> { // 查询走航任务及对应走航监测数据 val mission = missionRep.findOne(missionCode) ?: throw BizException("任务不存在") val data = realTimeDataRep.fetchData(mission) // 创建融合数据索引对象 val newGridData = GridData().apply { this.groupId = groupId dataTime = mission.startTime type = SatelliteDataType.Monitor.value.toByte() } satelliteGridRep.insertGridData(newGridData) // 查询网格单元格信息 val gridCellList = satelliteGridRep.fetchGridCell(groupId) // 将走航数据和卫星网格进行融合计算 val gridDataDetailList = SatelliteGridManage.dataFusion(data, newGridData, gridCellList) satelliteGridRep.insertGridDataDetail(gridDataDetailList) return gridDataDetailList } } src/test/kotlin/com/flightfeather/uav/UAVApplicationTests.kt
@@ -18,27 +18,6 @@ @Autowired lateinit var realTimeDataService: RealTimeDataService @Autowired lateinit var gridDataDetailMapper: GridDataDetailMapper /** * 刷新每组数据的数据排名 */ @Test fun refreshDataRank() { for (i in 29..39) { val dataDetailList = gridDataDetailMapper.selectByExample(Example(GridDataDetail::class.java).apply { createCriteria().andEqualTo("dataId", i) orderBy("pm25").desc() }) dataDetailList.forEachIndexed { i, d -> d?.rank = i + 1 gridDataDetailMapper.updateByPrimaryKey(d) } println("finish --${i}") } } @Test fun contextLoads() { } src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImplTest.kt
@@ -1,11 +1,14 @@ package com.flightfeather.uav.lightshare.service.impl import com.flightfeather.uav.domain.entity.GridDataDetail import com.flightfeather.uav.domain.mapper.GridDataDetailMapper import com.flightfeather.uav.lightshare.service.SatelliteDataCalculateService import org.junit.Test import org.junit.runner.RunWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.junit4.SpringRunner import tk.mybatis.mapper.entity.Example @RunWith(SpringRunner::class) @@ -14,6 +17,27 @@ @Autowired lateinit var satelliteDataCalculateService: SatelliteDataCalculateService @Autowired lateinit var gridDataDetailMapper: GridDataDetailMapper /** * 刷新每组数据的数据排名 */ @Test fun refreshDataRank() { for (i in 51..51) { val dataDetailList = gridDataDetailMapper.selectByExample(Example(GridDataDetail::class.java).apply { createCriteria().andEqualTo("dataId", i) orderBy("pm25").desc() }) dataDetailList.forEachIndexed { index, d -> d?.rank = index + 1 gridDataDetailMapper.updateByPrimaryKey(d) } println("finish --${i}") } } @Test fun splitGrid() { @@ -26,4 +50,10 @@ val res = satelliteDataCalculateService.splitData(4, 25) // println(res) } @Test fun dataFusion() { val res = satelliteDataCalculateService.dataFusion("SH-CN-20241216", 3) // println(res) } }