feiyu02
2025-09-30 94fee0b511279679b43e210878d3d36e5a14384b
src/main/kotlin/com/flightfeather/uav/biz/mission/MissionUtil.kt
@@ -1,7 +1,9 @@
package com.flightfeather.uav.biz.mission
import com.flightfeather.uav.common.net.AMapService
import com.flightfeather.uav.common.utils.MapUtil
import com.flightfeather.uav.domain.entity.BaseRealTimeData
import com.flightfeather.uav.domain.entity.avg
/**
 * 走航任务计算工具
@@ -15,18 +17,76 @@
     */
    fun calKilometres(data: List<BaseRealTimeData>): Double {
        var distance = .0
        for (i in 1 until data.size) {
            val a = data[i - 1]
            val b = data[i]
            if (a.longitude == null || a.latitude == null || b.longitude == null || b.latitude == null) continue
        var lastValidPoint: BaseRealTimeData? = null
            distance += MapUtil.getDistance(
                a.longitude!!.toDouble(),
                a.latitude!!.toDouble(),
                b.longitude!!.toDouble(),
                b.latitude!!.toDouble()
            )
        for (point in data) {
            // 跳过无效点
            if (point.longitude == null || point.latitude == null) continue
            // 如果存在上一个有效点,则计算距离
            lastValidPoint?.let { prevPoint ->
                distance += MapUtil.getDistance(
                    prevPoint.longitude!!.toDouble(),
                    prevPoint.latitude!!.toDouble(),
                    point.longitude!!.toDouble(),
                    point.latitude!!.toDouble()
                )
            }
            // 更新上一个有效点
            lastValidPoint = point
        }
        return distance
    }
}
    /**
     * 根据轨迹点计算所属区域(乡镇+街道)
     * @param data 走航轨迹点列表
     * @return 区域名称(乡镇+街道),若无法计算则返回null
     */
    @Suppress("UNCHECKED_CAST")
    fun calRegion(data: List<BaseRealTimeData>): String? {
        // 计算所有轨迹点的平均坐标(中心点)
        val avgData = data.avg()
        val pair = avgData.longitude?.toDouble() to avgData.latitude?.toDouble()
        // 若平均坐标无效则返回null
        if (pair.first == null || pair.second == null) return null
        // 将WGS84坐标转换为GCJ02坐标后进行逆地理编码获取地址信息
        val address = AMapService.reGeo(MapUtil.wgs84ToGcj02(pair as Pair<Double, Double>))
        // 返回乡镇和街道名称组合
        return address.township
    }
    /**
     * 数据清洗
     * 1. 修复由于硬件设备卡顿导致的数据采样时间不变问题,采用自动累加数据周期的方式修改采样时间
     * @param data 原始数据列表
     * @param period 数据周期,单位:秒
     * @return 清洗后需要修改的数据列表
     */
    fun dataClean(dataList: List<BaseRealTimeData>, period: Long): List<BaseRealTimeData> {
        val cleanedData = mutableListOf<BaseRealTimeData>()
        var errorData: BaseRealTimeData? = null
        dataList.forEachIndexed { index, data ->
            if (index == 0) {
                return@forEachIndexed
            }
            val lastOne = dataList[index - 1]
            if (errorData == null) {
                if (data.dataTime!!.time == lastOne.dataTime!!.time) {
                    data.dataTime?.time = lastOne.dataTime?.time!!.plus(period * 1000)
                    cleanedData.add(data)
                    errorData = lastOne
                }
            } else {
                if (data.dataTime!!.time == errorData!!.dataTime!!.time) {
                    data.dataTime?.time = lastOne.dataTime?.time!!.plus(period * 1000)
                    cleanedData.add(data)
                } else {
                    errorData = null
                }
            }
        }
        return cleanedData
    }
}