feiyu02
2025-03-21 e5bdf2e02090357cbd580d54e6cd2406dd541760
1. 新增卫星遥测网格热力图计算逻辑(待完成)
已修改15个文件
已添加8个文件
704 ■■■■ 文件已修改
src/main/kotlin/com/flightfeather/uav/biz/satellite/GridGroupOption.kt 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridManage.kt 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridUtil.kt 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/domain/entity/GridDataDetail.java 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteDataCalculateService.kt 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/model/BaseModel.kt 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/model/BaseSOP.kt 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/model/epw/EPWGridModel.kt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/model/epw/EPWModel.kt 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellAndData.kt 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellSop.kt 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridWindDirWeight.kt 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridWindDisWeight.kt 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/UnderwayGridDataPrep.kt 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/UnderwayGridModel.kt 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/generator/generatorConfig.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/GridDataDetailMapper.xml 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/kotlin/com/flightfeather/uav/Test.kt 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImplTest.kt 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/satellite/GridGroupOption.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
package com.flightfeather.uav.biz.satellite
/**
 * å«æ˜Ÿç½‘格组的参数,一个卫星网格组应该为矩形形式
 * @date 2025/3/21
 * @author feiyu02
 */
class GridGroupOption(
    // ç½‘格宽度,指东西方向上的网格数量
    val width: Int,
    // ç½‘格高度,指南北方向上的网格数量
    val height: Int,
    // ç»†åˆ†ç½‘格宽度,如果网格组是细分网格,则表示对应原始网格中单个网格下细分的网格数量
    val eachWith: Int,
    // ç»†åˆ†ç½‘格高度,如果网格组是细分网格,则表示对应原始网格中单个网格下细分的网格数量
    val eachHeight: Int,
)
src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridManage.kt
@@ -2,6 +2,7 @@
import com.flightfeather.uav.common.utils.MapUtil
import com.flightfeather.uav.domain.entity.*
import org.springframework.beans.BeanUtils
import kotlin.math.PI
import kotlin.math.sqrt
@@ -237,12 +238,13 @@
        realTimeDataList.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()
            SatelliteGridUtil.searchGirdIn(it.longitude!!.toDouble() to it.latitude!!.toDouble(), gridCellList)
                ?.let { cell ->
                    if (!dataMap.containsKey(cell)) {
                        dataMap[cell] = mutableListOf()
                    }
                    dataMap[cell]?.add(it)
                }
                dataMap[cell]?.add(it)
            }
        }
        // ç»Ÿè®¡æ¯ä¸ªç½‘格中的均值
@@ -250,11 +252,26 @@
        val gridDataDetailList = mutableListOf<GridDataDetail>()
        dataMap.forEach { (k, v) ->
            val avgData = v.avg()
            val dataDetail = GridDataDetail().apply {
            val dataDetail = GridDataDetail()
            BeanUtils.copyProperties(avgData, dataDetail)
            dataDetail.apply {
                dataId = gridData?.id
                groupId = k.groupId
                cellId = k.cellIndex
                pm25 = avgData.pm25
//                no2 = avgData.no2
//                co = avgData.co
//                h2s = avgData.h2s
//                so2 = avgData.so2
//                o3 = avgData.o3
//                pm25 = avgData.pm25
//                pm10 = avgData.pm10
//                temperature = avgData.temperature
//                humidity = avgData.humidity
//                voc = avgData.voc
//                noi = avgData.noi
//                no = avgData.no
//                windSpeed
//                windDirection
                rank
            }
            gridDataDetailList.add(dataDetail)
@@ -269,27 +286,6 @@
        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/biz/satellite/SatelliteGridUtil.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,78 @@
package com.flightfeather.uav.biz.satellite
import com.flightfeather.uav.common.utils.MapUtil
import com.flightfeather.uav.domain.entity.GridCell
import kotlin.math.ceil
/**
 * å«æ˜Ÿç½‘格计算工具
 */
object SatelliteGridUtil {
    /**
     * è®¡ç®—坐标点在哪个卫星网格内
     * @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
    }
    /**
     * è®¡ç®—扩散网格,根据给定网格,计算在其周围固定半径下的所有网格
     * ç½‘格的形式为原始卫星遥测网格以及细分网格
     * åŽŸå§‹å«æ˜Ÿé¥æµ‹ç½‘æ ¼çš„ç¼–å·é¡ºåºä¸ºä»Žå·¦åˆ°å³ï¼Œä»Žä¸Šåˆ°ä¸‹ç¼–å·ä¾æ¬¡é€’å¢ž
     * ç»†åˆ†ç½‘格在原始卫星遥测网格的基础上,每个网格内部按从左到右,从上到下编号依次递增
     * @param gridCellIndex ä¸­å¿ƒç‚¹ç½‘格索引值
     * @param gridCellList æ‰€æœ‰ç½‘格数组
     * @param option ç½‘格组的参数信息
     * @param searchLength æ‰©æ•£çš„网格半径数量
     * @return è®¡ç®—得出的扩散网格对象数组
     */
    fun searchDiffuseGrid(
        gridCellIndex: Int,
        gridCellList: List<GridCell?>,
        option: GridGroupOption,
        searchLength: Int,
    ): List<GridCell> {
        return emptyList()
    }
    /**
     * æ ¹æ®ç½‘格索引,获取其所在东西方向的网格索引范围
     * @param cellIndex ç½‘格索引
     * @param width ç½‘格宽度,指东西方向上的网格数量
     * @param height ç½‘格高度,指南北方向上的网格数量
     * @return è¿”回网格索引值范围
     */
    fun getCellWidthRange(cellIndex: Int, width: Int, height: Int): Pair<Double, Double>? {
        val total = width * height;
        val x = ceil(cellIndex.toDouble() / total) - 1;
        val first = 1 + x * total
        val last = width + x * total;
        var scale = 0;
        while (scale < height) {
            val min = first + scale * width;
            val max = last + scale * width;
            if (cellIndex >= min && cellIndex <= max) {
                return min to max
            }
            scale++;
        }
        return null
    }
}
src/main/kotlin/com/flightfeather/uav/domain/entity/GridDataDetail.java
@@ -26,10 +26,47 @@
    @Column(name = "cell_id")
    private Integer cellId;
    private Integer rank;
    @Column(name = "NO2")
    private Float no2;
    @Column(name = "CO")
    private Float co;
    @Column(name = "H2S")
    private Float h2s;
    @Column(name = "SO2")
    private Float so2;
    @Column(name = "O3")
    private Float o3;
    @Column(name = "PM25")
    private Float pm25;
    private Integer rank;
    @Column(name = "PM10")
    private Float pm10;
    private Float temperature;
    private Float humidity;
    @Column(name = "VOC")
    private Float voc;
    @Column(name = "NOI")
    private Float noi;
    @Column(name = "NO")
    private Float no;
    @Column(name = "wind_speed")
    private Float windSpeed;
    @Column(name = "wind_direction")
    private Float windDirection;
    /**
     * @return id
@@ -100,6 +137,90 @@
    }
    /**
     * @return rank
     */
    public Integer getRank() {
        return rank;
    }
    /**
     * @param rank
     */
    public void setRank(Integer rank) {
        this.rank = rank;
    }
    /**
     * @return NO2
     */
    public Float getNo2() {
        return no2;
    }
    /**
     * @param no2
     */
    public void setNo2(Float no2) {
        this.no2 = no2;
    }
    /**
     * @return CO
     */
    public Float getCo() {
        return co;
    }
    /**
     * @param co
     */
    public void setCo(Float co) {
        this.co = co;
    }
    /**
     * @return H2S
     */
    public Float getH2s() {
        return h2s;
    }
    /**
     * @param h2s
     */
    public void setH2s(Float h2s) {
        this.h2s = h2s;
    }
    /**
     * @return SO2
     */
    public Float getSo2() {
        return so2;
    }
    /**
     * @param so2
     */
    public void setSo2(Float so2) {
        this.so2 = so2;
    }
    /**
     * @return O3
     */
    public Float getO3() {
        return o3;
    }
    /**
     * @param o3
     */
    public void setO3(Float o3) {
        this.o3 = o3;
    }
    /**
     * @return PM25
     */
    public Float getPm25() {
@@ -114,16 +235,114 @@
    }
    /**
     * @return rank
     * @return PM10
     */
    public Integer getRank() {
        return rank;
    public Float getPm10() {
        return pm10;
    }
    /**
     * @param rank
     * @param pm10
     */
    public void setRank(Integer rank) {
        this.rank = rank;
    public void setPm10(Float pm10) {
        this.pm10 = pm10;
    }
    /**
     * @return temperature
     */
    public Float getTemperature() {
        return temperature;
    }
    /**
     * @param temperature
     */
    public void setTemperature(Float temperature) {
        this.temperature = temperature;
    }
    /**
     * @return humidity
     */
    public Float getHumidity() {
        return humidity;
    }
    /**
     * @param humidity
     */
    public void setHumidity(Float humidity) {
        this.humidity = humidity;
    }
    /**
     * @return VOC
     */
    public Float getVoc() {
        return voc;
    }
    /**
     * @param voc
     */
    public void setVoc(Float voc) {
        this.voc = voc;
    }
    /**
     * @return NOI
     */
    public Float getNoi() {
        return noi;
    }
    /**
     * @param noi
     */
    public void setNoi(Float noi) {
        this.noi = noi;
    }
    /**
     * @return NO
     */
    public Float getNo() {
        return no;
    }
    /**
     * @param no
     */
    public void setNo(Float no) {
        this.no = no;
    }
    /**
     * @return wind_speed
     */
    public Float getWindSpeed() {
        return windSpeed;
    }
    /**
     * @param windSpeed
     */
    public void setWindSpeed(Float windSpeed) {
        this.windSpeed = windSpeed;
    }
    /**
     * @return wind_direction
     */
    public Float getWindDirection() {
        return windDirection;
    }
    /**
     * @param windDirection
     */
    public void setWindDirection(Float windDirection) {
        this.windDirection = windDirection;
    }
}
src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt
@@ -1,6 +1,5 @@
package com.flightfeather.uav.lightshare.bean
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonInclude
import com.flightfeather.uav.model.BaseMData
import com.flightfeather.uav.socket.bean.AirData
src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteDataCalculateService.kt
@@ -36,4 +36,11 @@
     * @param groupId
     */
    fun dataFusion(missionCode: String, groupId: Int): List<GridDataDetail?>
    /**
     * å°†èµ°èˆªç½‘格数据生成对应的热力网格图
     * @param groupId ä½¿ç”¨çš„网格组id
     * @param gridDataDetail ä½¿ç”¨çš„走航网格数据
     */
    fun buildHeatmap(groupId: Int, gridDataDetail: List<GridDataDetail>): List<GridDataDetail>
}
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt
@@ -180,4 +180,9 @@
            return gridDataDetailList
        }
    }
    override fun buildHeatmap(groupId: Int, gridDataDetail: List<GridDataDetail>): List<GridDataDetail> {
        val gridCellList = satelliteGridRep.fetchGridCell(groupId)
    }
}
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt
@@ -58,7 +58,7 @@
        val res =  satelliteGridRep.fetchGridDataDetail(dataId, groupId, cellId)
        res.forEach {
            if (it?.pm25 != null) {
                it.pm25 = round(it.pm25 * 100) / 100
                it.pm25 = round(it.pm25 * 10) / 10
            }
        }
        return res
src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt
@@ -145,5 +145,10 @@
        @ApiParam("网格组id") @RequestParam groupId: Int,
    ) = resPack { satelliteDataCalculateService.dataFusion(missionCode, groupId) }
    @ApiOperation(value = "生成走航热力图")
    @PostMapping("/product/underway/heatmap/build")
    fun buildUnderwayHeatmap(
        @ApiParam("使用的网格组id") @RequestParam groupId: Int,
        @ApiParam("使用的走航网格数据") @RequestBody gridDataDetail: List<GridDataDetail>
    ) = resPack { satelliteDataCalculateService.buildHeatmap(groupId, gridDataDetail) }
}
src/main/kotlin/com/flightfeather/uav/model/BaseModel.kt
@@ -3,7 +3,6 @@
import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.common.utils.ExcelUtil
import com.flightfeather.uav.socket.eunm.FactorType
import org.apache.poi.hssf.usermodel.HSSFWorkbook
import org.apache.poi.xssf.streaming.SXSSFWorkbook
import java.io.File
import java.io.FileOutputStream
@@ -14,7 +13,7 @@
 * æ±¡æŸ“源影响程度权重分析模型
 * åŸºç±»
 */
abstract class BaseModel<M : BaseMData> {
abstract class BaseModel<M : BaseMData, S: BaseSOP> {
    data class ResultCell(
        var total: Double = 0.0,
@@ -27,26 +26,26 @@
        }
    }
    abstract var dataPrep: BaseDataPrep<M, BaseSOP>
    abstract var dataPrep: BaseDataPrep<M, S>
    // æƒé‡å› å­ï¼Œåœ¨è¿›è¡Œè®¡ç®—分析时使用的监测因子
    abstract var factorTypes: List<FactorType>
    // æƒé‡å€¼ï¼Œå¤šç§æƒé‡è¿›è¡Œä¹˜ç§¯è®¡ç®—
    abstract var weights: List<BaseWeight<M, BaseSOP>>
    abstract var weights: List<BaseWeight<M, S>>
    // è®¡ç®—结果
    private val rMap = mutableMapOf<String, MutableMap<String, MutableMap<String, ResultCell>>>()
    // ç»“果筛选方式
    abstract var sections: List<BaseSection<M, BaseSOP>>
    abstract var sections: List<BaseSection<M, S>>
    /**
     * æ±¡æŸ“源影响程度计算
     * @param mDataList ç›‘测数据集合
     * @param sopList æ±¡æŸ“源集合
     */
    fun execute(mDataList: List<M>, sopList: List<BaseSOP>, hasNext: Boolean = false) {
    open fun execute(mDataList: List<M>, sopList: List<S>, hasNext: Boolean = false) {
        if (!hasNext) rMap.clear()
        //1. æ•°æ®é¢„处理
@@ -68,7 +67,7 @@
     * @param mData ç›‘测数据
     * @param sop æ±¡æŸ“源
     */
    private fun weightCompute(mData: M, sop: BaseSOP) {
    private fun weightCompute(mData: M, sop: S) {
        val effect = BaseEffect(sop.sourceId, sop.sourceName, sop.index)
        // å°†åŽŸç›‘æµ‹æ•°æ®æŒ‰ç…§æƒé‡è®¡ç®—å‡ºç»“æžœå€¼
@@ -132,7 +131,7 @@
                        val lKey = "$se($factorType)"
                        if (lMap.containsKey(lKey)) {
                            val resultCell = lMap[lKey] ?: return@type
                            val size = resultCell.count
//                            val size = resultCell.count
                            // æ·»åŠ è¯¥åˆ†ç±»ä½œä¸ºè¡¨å¤´
                            val h = lKey
//                            val h = "$lKey($size)"
@@ -234,5 +233,5 @@
    /**
     * æ±¡æŸ“源数据合法性检查
     */
    abstract fun sopCheck(s: BaseSOP): Boolean
    abstract fun sopCheck(s: S): Boolean
}
src/main/kotlin/com/flightfeather/uav/model/BaseSOP.kt
@@ -6,12 +6,18 @@
 * Source of pollution
 * æ±¡æŸ“源 åŸºç±»
 */
open class BaseSOP(
open class BaseSOP() {
    // æ±¡æŸ“源标识
    var sourceId: String,
    var sourceName: String,
    var index: String
) {
    lateinit var sourceId: String
    lateinit var sourceName: String
    lateinit var index: String
    constructor(sourceId: String, sourceName: String, index: String) : this() {
        this.sourceId = sourceId
        this.sourceName = sourceName
        this.index = index
    }
    /**
     * ä¸­å¿ƒç»åº¦
     */
src/main/kotlin/com/flightfeather/uav/model/epw/EPWGridModel.kt
@@ -10,7 +10,7 @@
 * æ ¹æ®èµ°èˆªç›‘测数据、定点监测数据,结合风速、风向、监测点与网格中心的相对位置等因素,计算网格区域对监测区域的影响程度
 * @author riku
 */
class EPWGridModel : BaseModel<DataVo>() {
class EPWGridModel : BaseModel<DataVo, BaseSOP>() {
    // é»˜è®¤ç›‘测点经纬度
    var defaultLocation: Pair<Double, Double>? = null
        set(value) {
src/main/kotlin/com/flightfeather/uav/model/epw/EPWModel.kt
@@ -1,6 +1,5 @@
package com.flightfeather.uav.model.epw
import com.flightfeather.uav.lightshare.bean.CompanySOP
import com.flightfeather.uav.lightshare.bean.DataVo
import com.flightfeather.uav.model.*
import com.flightfeather.uav.socket.eunm.FactorType
@@ -11,7 +10,7 @@
 * æ ¹æ®èµ°èˆªç›‘测数据,结合风速、风向、监测点与企业的相对位置等因素,计算企业对监测区域的影响程度
 * @author riku
 */
class EPWModel : BaseModel<DataVo>() {
class EPWModel : BaseModel<DataVo, BaseSOP>() {
    // é»˜è®¤ç›‘测点经纬度
    var defaultLocation: Pair<Double, Double>? = null
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellAndData.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.flightfeather.uav.model.underwaygrid
import com.flightfeather.uav.domain.entity.GridCell
import com.flightfeather.uav.domain.entity.GridDataDetail
import com.flightfeather.uav.model.BaseMData
import com.flightfeather.uav.socket.eunm.FactorType
import com.flightfeather.uav.socket.eunm.FactorType.*
/**
 * å«æ˜Ÿç½‘格坐标和监测数据
 * @date 2025/3/21
 * @author feiyu02
 */
class GridCellAndData(val gridCell: GridCell, val gridDataDetail: GridDataDetail): BaseMData() {
    override fun getFactorData(type: FactorType): Double? {
        return when (type) {
//            NO2 -> NO2
//            CO -> CO
//            H2S -> H2S
//            SO2 -> SO2
//            O3 -> O3
            PM25 -> gridDataDetail.pm25.toDouble()
//            PM10 -> PM10
//            TEMPERATURE -> TEMPERATURE
//            HUMIDITY -> HUMIDITY
//            VOC -> VOC
//            NOI -> NOI
//            LNG -> LNG
//            LAT -> LAT
//            VELOCITY -> VELOCITY
//            TIME -> TIME
//            WIND_SPEED -> WIND_SPEED
//            WIND_DIRECTION -> WIND_DIRECTION
//            HEIGHT -> HEIGHT
//            NO -> NO
            else -> null
        }
    }
}
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellSop.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.flightfeather.uav.model.underwaygrid
import com.flightfeather.uav.domain.entity.GridCell
import com.flightfeather.uav.model.BaseSOP
/**
 * å«æ˜Ÿæ±¡æŸ“源网格
 * @date 2025/3/21
 * @author feiyu02
 */
class GridCellSop : BaseSOP {
    val gridCell:GridCell
    constructor(gridCell: GridCell) : super(){
        this.gridCell = gridCell
    }
    constructor(gridCell: GridCell, sourceId: String, sourceName: String, index: String) : super(
        sourceId,
        sourceName, index
    ){
        this.gridCell = gridCell
    }
}
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridWindDirWeight.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.flightfeather.uav.model.underwaygrid
import com.flightfeather.uav.model.BaseWeight
import com.flightfeather.uav.socket.eunm.FactorType
import java.math.BigDecimal
import kotlin.math.PI
import kotlin.math.abs
import kotlin.math.atan2
/**
 * é£Žå‘权重
 * @date 2025/3/21
 * @author feiyu02
 */
class GridWindDirWeight : BaseWeight<GridCellAndData, GridCellSop>() {
    override val tag: String = "风向权重"
    override val sectionValues: List<Double> = listOf(22.5, 67.5, 112.5, 157.5, 180.0)
    override val weights: List<Double> = listOf(1.0, 0.8, 0.5, 0.2, 0.1)
    override fun onWeightFactor(mData: GridCellAndData, sop: GridCellSop): Double? {
        val p1 = Pair(mData.gridCell.longitude, mData.gridCell.latitude)
        val p2 = Pair(sop.gridCell.longitude, sop.gridCell.latitude)
        val wd = mData.getFactorData(FactorType.WIND_DIRECTION) ?: 0.0
        return getAngle(p1, p2, wd)
    }
    private fun getAngle(p1: Pair<BigDecimal, BigDecimal>, p2: Pair<BigDecimal, BigDecimal>, wd: Double): Double {
        val dx = p2.first - p1.first
        val dy = p2.second - p1.second
        var x1 = atan2(dy.toDouble(), dx.toDouble()) * 180 / PI + 180
        if (x1 < 0) x1 += 360
        var x2 = 270 - wd
        if (x2 < 0) x2 += 360
        x1 = abs(x2 - x1)
        if (x1 > 180) x1 = 360 - x1
        return x1
    }
}
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridWindDisWeight.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
package com.flightfeather.uav.model.underwaygrid
import com.flightfeather.uav.model.BaseWeight
import com.flightfeather.uav.socket.eunm.FactorType
import java.math.BigDecimal
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.sqrt
/**
 * é£Žé€Ÿè·ç¦»æƒé‡
 * ç›‘测点与污染源之间的物理距离与当前风速得出的权重
 * @date 2025/3/21
 * @author feiyu02
 */
class GridWindDisWeight : BaseWeight<GridCellAndData, GridCellSop>() {
    override val tag: String = "风速距离权重"
    override val sectionValues: List<Double> = listOf(2.0, 5.0, 8.0, 12.0, 20.0, 30.0)
    override val weights: List<Double> = listOf(1.0, 0.8, 0.6, 0.5, 0.3, 0.0)
    override fun onWeightFactor(mData: GridCellAndData, sop: GridCellSop): Double? {
        val p1 = Pair(mData.gridCell.longitude, mData.gridCell.latitude)
        val p2 = Pair(sop.gridCell.longitude, sop.gridCell.latitude)
        val ws = mData.getFactorData(FactorType.WIND_SPEED)
        return if (ws == null) null else getWindSpeed(p1, p2, ws)
    }
    private fun getWindSpeed(p1: Pair<BigDecimal, BigDecimal>, p2: Pair<BigDecimal, BigDecimal>, ws: Double): Double {
        val dx = (p2.first - p1.first).toDouble()
        val dy = (p2.second - p1.second).toDouble()
        val dis = sqrt(abs(dx * dx) + abs(dy * dy)) * 100
        val min = dis * 1000 / max(ws, 1.0) / 60
        return min
    }
}
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/UnderwayGridDataPrep.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.flightfeather.uav.model.underwaygrid
import com.flightfeather.uav.model.BaseDataPrep
/**
 * èµ°èˆªç½‘格数据预处理
 * @date 2025/3/21
 * @author feiyu02
 */
class UnderwayGridDataPrep : BaseDataPrep<GridCellAndData, GridCellSop>() {
    override fun mDataPrep(mDataList: List<GridCellAndData>): List<GridCellAndData> {
        return mDataList
    }
    override fun sopPrep(sopList: List<GridCellSop>): List<GridCellSop> {
        return sopList
    }
}
src/main/kotlin/com/flightfeather/uav/model/underwaygrid/UnderwayGridModel.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package com.flightfeather.uav.model.underwaygrid
import com.flightfeather.uav.model.BaseDataPrep
import com.flightfeather.uav.model.BaseModel
import com.flightfeather.uav.model.BaseSection
import com.flightfeather.uav.model.BaseWeight
import com.flightfeather.uav.model.epw.WeightType
import com.flightfeather.uav.socket.eunm.FactorType
/**
 *
 * @date 2025/3/21
 * @author feiyu02
 */
class UnderwayGridModel : BaseModel<GridCellAndData, GridCellSop>() {
    override var dataPrep: BaseDataPrep<GridCellAndData, GridCellSop> = UnderwayGridDataPrep()
    override var factorTypes: List<FactorType> = WeightType.weightType
    override var weights: List<BaseWeight<GridCellAndData, GridCellSop>> = listOf(GridWindDirWeight(), GridWindDisWeight())
    override var sections: List<BaseSection<GridCellAndData, GridCellSop>> = emptyList()
    override fun mDataCheck(m: GridCellAndData): Boolean {
        return m.gridDataDetail.pm25 != null
    }
    override fun sopCheck(s: GridCellSop): Boolean {
        return s.gridCell.longitude != null && s.gridCell.latitude != null
    }
}
src/main/resources/generator/generatorConfig.xml
@@ -66,9 +66,9 @@
<!--        <table tableName="real_time_data_grid_opt" domainObjectName="RealTimeDataGridOpt" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
<!--        <table tableName="scene_info" domainObjectName="SceneInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
<!--        <table tableName="segment_info" domainObjectName="SegmentInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
        <table tableName="grid_group" domainObjectName="GridGroup" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>
<!--        <table tableName="grid_group" domainObjectName="GridGroup" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
<!--        <table tableName="grid_cell" domainObjectName="GridCell" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
<!--        <table tableName="grid_data" domainObjectName="GridData" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
<!--        <table tableName="grid_data_detail" domainObjectName="GridDataDetail" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
        <table tableName="grid_data_detail" domainObjectName="GridDataDetail" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>
    </context>
</generatorConfiguration>
src/main/resources/mapper/GridDataDetailMapper.xml
@@ -9,14 +9,28 @@
    <result column="data_id" jdbcType="INTEGER" property="dataId" />
    <result column="group_id" jdbcType="INTEGER" property="groupId" />
    <result column="cell_id" jdbcType="INTEGER" property="cellId" />
    <result column="PM25" jdbcType="REAL" property="pm25" />
    <result column="rank" jdbcType="INTEGER" property="rank" />
    <result column="NO2" jdbcType="REAL" property="no2" />
    <result column="CO" jdbcType="REAL" property="co" />
    <result column="H2S" jdbcType="REAL" property="h2s" />
    <result column="SO2" jdbcType="REAL" property="so2" />
    <result column="O3" jdbcType="REAL" property="o3" />
    <result column="PM25" jdbcType="REAL" property="pm25" />
    <result column="PM10" jdbcType="REAL" property="pm10" />
    <result column="temperature" jdbcType="REAL" property="temperature" />
    <result column="humidity" jdbcType="REAL" property="humidity" />
    <result column="VOC" jdbcType="REAL" property="voc" />
    <result column="NOI" jdbcType="REAL" property="noi" />
    <result column="NO" jdbcType="REAL" property="no" />
    <result column="wind_speed" jdbcType="REAL" property="windSpeed" />
    <result column="wind_direction" jdbcType="REAL" property="windDirection" />
  </resultMap>
  <sql id="Base_Column_List">
    <!--
      WARNING - @mbg.generated
    -->
    id, data_id, group_id, cell_id, PM25, rank
    id, data_id, group_id, cell_id, rank, NO2, CO, H2S, SO2, O3, PM25, PM10, temperature,
    humidity, VOC, NOI, NO, wind_speed, wind_direction
  </sql>
  <!-- æ·»åŠ æ‰¹é‡æ›´æ–°PM25的函数 -->
src/test/kotlin/com/flightfeather/uav/Test.kt
@@ -3,18 +3,18 @@
import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.common.utils.FileExchange
import com.flightfeather.uav.common.utils.FileUtil
import com.flightfeather.uav.domain.entity.BaseRealTimeData
import com.flightfeather.uav.domain.entity.Company
import com.flightfeather.uav.lightshare.eunm.SatelliteDataType
import com.flightfeather.uav.domain.entity.GridDataDetail
import com.flightfeather.uav.socket.bean.DataUnit
import com.flightfeather.uav.socket.decoder.AirDataDecoder
import com.flightfeather.uav.socket.eunm.AirCommandUnit
import com.google.gson.Gson
import org.jetbrains.kotlin.konan.util.visibleName
import org.junit.Test
import org.springframework.beans.BeanUtils
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStreamWriter
import java.math.BigDecimal
import java.text.SimpleDateFormat
import java.util.*
@@ -56,7 +56,8 @@
    @Test
    fun listCopy() {
        val l1 = listOf(Company().apply { ciGuid = "a" }, Company().apply { ciGuid = "b" }, Company().apply { ciGuid = "c" })
        val l1 =
            listOf(Company().apply { ciGuid = "a" }, Company().apply { ciGuid = "b" }, Company().apply { ciGuid = "c" })
        val l2 = mutableListOf<Company>().apply { addAll(l1) }
        l2[1].ciGuid = "d"
        println(l1)
@@ -73,8 +74,9 @@
    }
    @Test
    fun get_crc16(){
        val dataSegment = "QN=20210713133901044;ST=22;CN=2011;PW=555555;MN=FYHB0DT0100001;Flag=1;CP=&&DataTime=20210713133800;a34001-Avg=0.017,a34001-CPM=3.9,a34001-Flag=N;a50001-Avg=71.1,a50001-Flag=N;a01001-Avg=34.0,a01001-Flag=N;a01002-Avg=59.3,a01002-Flag=N;a01007-Avg=0.6,a01007-Flag=N;a01008-Avg=256.3,a01008-Flag=N;Period=1;Scale=1.0;SelfTemp=0.0;SelfHum=0.0;IsReplacement=N&&"
    fun get_crc16() {
        val dataSegment =
            "QN=20210713133901044;ST=22;CN=2011;PW=555555;MN=FYHB0DT0100001;Flag=1;CP=&&DataTime=20210713133800;a34001-Avg=0.017,a34001-CPM=3.9,a34001-Flag=N;a50001-Avg=71.1,a50001-Flag=N;a01001-Avg=34.0,a01001-Flag=N;a01002-Avg=59.3,a01002-Flag=N;a01007-Avg=0.6,a01007-Flag=N;a01008-Avg=256.3,a01008-Flag=N;Period=1;Scale=1.0;SelfTemp=0.0;SelfHum=0.0;IsReplacement=N&&"
        var CRC = 0x0000ffff
        val POLYNOMIAL = 0x0000a001
        var i: Int
@@ -129,11 +131,25 @@
    @Test
    fun foo17() {
        println(SatelliteDataType.Original.name)
        println(SatelliteDataType.Original.value)
        println(SatelliteDataType.Original.ordinal)
        println(SatelliteDataType.Original.toString())
        println(SatelliteDataType.Original.visibleName)
        println(SatelliteDataType.Original)
        val avgData = BaseRealTimeData().apply {
            no2 = 50f
            co = 50f
            h2s = 50f
            so2 = 50f
            o3 = 50f
            pm25 = 50f
            pm10 = 50f
            temperature = 50f
            humidity = 50f
            voc = 50f
            noi = 50f
            no = 50f
            windSpeed = 2f
            windDirection = 240f
        }
        val dataDetail = GridDataDetail()
        BeanUtils.copyProperties(avgData, dataDetail)
        println(dataDetail)
    }
}
src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImplTest.kt
@@ -50,7 +50,7 @@
        val groupIdList = listOf(2, 4)
        val dataId = listOf(34, 29, 25, 18, 8)
        groupIdList.forEach {g ->
        groupIdList.forEach { g ->
            dataId.forEach { d ->
                satelliteDataCalculateService.splitData(g, d)
            }
@@ -61,7 +61,15 @@
    @Test
    fun dataFusion() {
        val missionList =
            listOf("SH-CN-20241202", "SH-CN-20241127", "SH-CN-20241126-1", "SH-CN-20241126-2", "SH-CN-20241108", "SH-CN-20240823")
            listOf(
                "SH-CN-20241216",
                "SH-CN-20241202",
                "SH-CN-20241127",
                "SH-CN-20241126-1",
                "SH-CN-20241126-2",
                "SH-CN-20241108",
                "SH-CN-20240823"
            )
        missionList.forEach { m ->
            satelliteDataCalculateService.dataFusion(m, 3)
        }