zhaowenyu
2026-02-11 8d96f0030bf4b61a94c1fa7d7bf5f23026a21bc7
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
package com.ard.work.component.websocket.handler;
 
import com.ard.data.noflyzone.domain.ArdNoFlyBox;
import com.ard.data.noflyzone.domain.ArdNoFlyZone;
import com.ard.data.noflyzone.domain.Vertex;
import com.ard.data.noflyzone.service.IArdNoFlyZoneService;
import com.ard.data.noflyzone.utils.NoFlyZoneUtils;
import com.ard.work.domain.cache.UavTelemetryDataCache;
import com.ard.work.domain.dto.NoFlyDistanceDTO;
import com.ard.work.domain.dto.telemetry.TelemetryData;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
 
/**
 * 禁飞区距离管理器
 * @author liuyaping
 * @date 2021/3/22
 */
@Component
public class NoFlyDistanceManager extends BaseSubscriptionManager<NoFlyDistanceDTO> {
 
    @Resource
    private IArdNoFlyZoneService ardNoFlyZoneService;
 
    @Override
    protected NoFlyDistanceDTO getData(String boxSn) {
        TelemetryData telemetryData = UavTelemetryDataCache.get(boxSn);
        if (telemetryData == null) return null;
 
        Vertex current = new Vertex(telemetryData.getLng(), telemetryData.getLat());
 
        List<ArdNoFlyZone> zones = ardNoFlyZoneService.selectArdNoFlyZoneList(new ArdNoFlyZone());
        if (zones.isEmpty()) return null;
 
        double minDistance = Double.MAX_VALUE;
        ArdNoFlyZone nearestZone = null;
 
        for (ArdNoFlyZone zone : zones) {
 
            ArdNoFlyBox box = zone.getArdNoFlyBox();
            if (box == null) continue;
 
            // ⭐ 外扩 50 米
            ArdNoFlyBox expanded = expandBoxByMeter(box, 50);
 
            // ⭐ 包围盒快速排除必须使用 expanded,而不是 box
            if (current.x < expanded.getMinx() || current.x > expanded.getMaxx() ||
                    current.y < expanded.getMiny() || current.y > expanded.getMaxy()) {
                continue;
            }
 
            // 计算 polygon 距离
            List<Vertex> polygon = zone.getVertices();
            if (polygon == null || polygon.size() < 3) continue;
 
            double distance = NoFlyZoneUtils.pointToPolygonDistance(current, polygon);
 
            if (distance < minDistance) {
                minDistance = distance;
                nearestZone = zone;
            }
        }
 
        if (nearestZone == null) return null;
 
        return NoFlyDistanceDTO.builder()
                .boxSn(boxSn)
                .zoneName(nearestZone.getName())
                .distance(minDistance)              // 米
                .inNoFlyZone(minDistance == 0)
                .build();
    }
 
    // 外扩包围盒多少米
    private ArdNoFlyBox expandBoxByMeter(ArdNoFlyBox box, double meter) {
 
        // 计算经纬度偏移
        double latShift = meter / 111320.0;  // 纬度方向
        double lngShift = meter / (111320.0 * Math.cos(Math.toRadians(
                (box.getMiny() + box.getMaxy()) / 2
        ))); // 经度方向与纬度相关
 
        return new ArdNoFlyBox(
                box.getMinx() - lngShift,
                box.getMiny() - latShift,
                box.getMaxx() + lngShift,
                box.getMaxy() + latShift
        );
    }
 
 
    @Override
    protected String getMessageType() {
        return "noFlyZoneDistance";
    }
 
 
 
}