package com.flightfeather.uav.biz.dataprocess
|
|
import com.flightfeather.uav.common.location.TrackSegment
|
import com.flightfeather.uav.common.net.AMapService
|
import com.flightfeather.uav.domain.entity.BaseRealTimeData
|
import com.flightfeather.uav.domain.entity.Mission
|
import com.flightfeather.uav.domain.entity.SegmentInfo
|
import com.flightfeather.uav.domain.entity.avg
|
import com.flightfeather.uav.domain.repository.RealTimeDataRep
|
import com.flightfeather.uav.domain.repository.SegmentInfoRep
|
import org.springframework.stereotype.Component
|
import java.math.BigDecimal
|
|
/**
|
* 走航轨迹按照路段进行分割
|
* @date 2024/7/4
|
* @author feiyu02
|
*/
|
@Component
|
class RoadSegment(
|
private val realTimeDataRep: RealTimeDataRep,
|
private val segmentInfoRep: SegmentInfoRep,
|
) {
|
|
fun handle(mission: Mission) {
|
// 获取数据分段
|
val data = mutableListOf<BaseRealTimeData>()
|
realTimeDataRep.fetchData(mission).forEach {
|
// 去除无效经纬度
|
if ((it.longitude != null && it.longitude != BigDecimal.ZERO)
|
&& (it.latitude != null && it.latitude != BigDecimal.ZERO)
|
) {
|
data.add(it)
|
}
|
}
|
val sData = TrackSegment.segmentWithRoad(data)
|
// 根据每个分段的GPS坐标均值通过高德API转换为高德坐标
|
val avgGPS = mutableListOf<Pair<Double, Double>>()
|
sData.forEach {
|
val d = it.avg()
|
if (d.longitude != null && d.latitude != null) {
|
avgGPS.add(d.longitude!!.toDouble() to d.latitude!!.toDouble())
|
}
|
}
|
val gdGPS = mutableListOf<Pair<Double, Double>>()
|
val _avgGPS = prepareForConvert(avgGPS)
|
_avgGPS.forEach {
|
gdGPS.addAll(AMapService.coordinateConvert(it))
|
}
|
// 通过高德API查询坐标对应的路段
|
val segmentInfoList = mutableListOf<SegmentInfo>()
|
gdGPS.forEachIndexed { i, pair ->
|
val address = AMapService.reGeo(pair)
|
segmentInfoList.add(SegmentInfo().apply {
|
missionCode = mission.missionCode
|
deviceCode = mission.deviceCode
|
startTime = sData[i][0].dataTime
|
endTime = sData[i].last().dataTime
|
provinceName = address.province
|
cityCode = address.citycode
|
districtCode = address.adcode
|
districtName = address.district
|
townCode = address.towncode
|
towmName = address.township
|
street = address.street
|
})
|
}
|
// 结果入库
|
saveResult(segmentInfoList)
|
}
|
|
/**
|
* 坐标转换分段准备
|
* 高德API的坐标转换接口一次访问最多支持40对坐标
|
*/
|
private fun prepareForConvert(gpsList: List<Pair<Double, Double>>): List<List<Pair<Double, Double>>> {
|
val res = mutableListOf<List<Pair<Double, Double>>>()
|
val maxLen = 40
|
var start = 0
|
var end = start + maxLen
|
while (end < gpsList.size) {
|
res.add(gpsList.subList(start, end))
|
start += maxLen
|
end += maxLen
|
}
|
if (start < gpsList.size) {
|
res.add(gpsList.subList(start, gpsList.size))
|
}
|
return res
|
}
|
|
/**
|
* 结果入库
|
* 入库之前,将连续并属于同一道路的记录合并
|
*/
|
private fun saveResult(segmentInfoList:List<SegmentInfo>) {
|
val res = mutableListOf<SegmentInfo>()
|
segmentInfoList.forEach { s ->
|
// 判断当前记录和上个记录是否数据同一条道路
|
if (res.isNotEmpty()) {
|
val lastOne = res.last()
|
// 若属于同一道路,合并
|
if (lastOne.street == s.street) {
|
lastOne.endTime = s.endTime
|
} else {
|
res.add(s)
|
}
|
} else {
|
res.add(s)
|
}
|
}
|
segmentInfoRep.insert(res)
|
}
|
}
|