1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package cn.flightfeather.supervision.business.location
 
import cn.flightfeather.supervision.common.utils.ExcelUtil
import cn.flightfeather.supervision.domain.ds1.entity.Scense
import cn.flightfeather.supervision.domain.ds1.mapper.ScenseMapper
import org.springframework.stereotype.Component
import tk.mybatis.mapper.entity.Example
import kotlin.math.PI
 
/**
 * 路段周边查询
 */
@Component
class LocationRoadNearby(private val scenseMapper: ScenseMapper) {
 
    private val utilFile = UtilFile()
 
    data class BasePlace(
        val name: String,
        val sP: Pair<Double, Double>,
        val eP: Pair<Double, Double>,
    )
 
    private fun searchOne(basePlace: BasePlace, distance: Double) {
        val range = rangeRestriction(basePlace, distance)
        getSceneFromDb(range).forEach { utilFile.parseRow(it) }
    }
 
    /**
     * 搜寻参考路段给定半径内的点位
     * @param basePlace 参考点位信息
     * @param distance 搜索半径
     */
    fun search(basePlace: BasePlace, distance: Double) {
        utilFile.reset()
        searchOne(basePlace, distance)
        utilFile.outPutToFile()
    }
 
    fun searchList(pList: List<BasePlace>, distance: Double) {
        utilFile.reset()
        pList.forEach {
            val range = rangeRestriction(it, distance)
            val sceneList = getSceneFromDb(range)
            if (sceneList.isEmpty()) {
                utilFile.addRow(listOf(it.name))
            }
            sceneList.forEachIndexed { index, s->
                utilFile.parseRow(s)
                if (index == 0) {
                    utilFile.updateLastRow(0, ExcelUtil.MyCell(it.name, sceneList.size))
                }
            }
            utilFile.index = 1
        }
        utilFile.outPutToFile()
    }
 
    /**
     * 根据圆心和半径查询范围内监测点(当前简化操作,改为以直径为边长的正方形范围)
     * @param center 圆心
     * @param radius 半径(单位:米)
     * @return 场景列表
     */
    fun searchByRadius(center: Pair<Double, Double>, radius: Double): List<Scense> {
        // 求经度的最小值
        val minLng = CoordinateUtil.getPointByLen(center, radius, PI * 1.5).first
        // 求经度的最大值
        val maxLng = CoordinateUtil.getPointByLen(center, radius, PI * 0.5).first
        // 求纬度的最小值
        val minLat = CoordinateUtil.getPointByLen(center, radius, PI).second
        // 求纬度的最大值
        val maxLat = CoordinateUtil.getPointByLen(center, radius, .0).second
 
        val list = listOf(minLng, maxLng, minLat, maxLat)
        return getSceneFromDb(list)
    }
 
    /**
     * 范围限定
     * 根据路段的始末点坐标和查询半径,计算最大可能的范围矩形,得出经纬度的最大最小值
     */
    private fun rangeRestriction(basePlace: BasePlace, distance: Double): List<Double> {
        // 求经度的最小值
        val p1 = if (basePlace.sP.first < basePlace.eP.first) basePlace.sP else basePlace.eP
        val minLng = CoordinateUtil.getPointByLen(p1, distance, PI * 1.5).first
        // 求经度的最大值
        val p2 = if (basePlace.sP.first > basePlace.eP.first) basePlace.sP else basePlace.eP
        val maxLng = CoordinateUtil.getPointByLen(p2, distance, PI * 0.5).first
        // 求纬度的最小值
        val p3 = if (basePlace.sP.second < basePlace.eP.second) basePlace.sP else basePlace.eP
        val minLat = CoordinateUtil.getPointByLen(p3, distance, PI).second
        // 求纬度的最大值
        val p4 = if (basePlace.sP.second > basePlace.eP.second) basePlace.sP else basePlace.eP
        val maxLat = CoordinateUtil.getPointByLen(p4, distance, .0).second
 
        return listOf(minLng, maxLng, minLat, maxLat)
    }
 
    /**
     * 根据限定矩形范围从数据库获取符合条件的点位
     */
    private fun getSceneFromDb(range: List<Double>): List<Scense> {
        return scenseMapper.selectByExample(Example(Scense::class.java).apply {
            createCriteria().andGreaterThanOrEqualTo("longitude", range[0])
                .andLessThanOrEqualTo("longitude", range[1])
                .andGreaterThanOrEqualTo("latitude", range[2])
                .andLessThanOrEqualTo("latitude", range[3])
            and(createCriteria().orNotEqualTo("extension1", "0")
                .orIsNull("extension1"))
        })
    }
}