zhaowenyu
2025-12-13 145e705946adf1e47512f2450e8bdd42662751e6
ard-work/src/main/java/com/ard/work/component/websocket/handler/NoFlyDistanceManager.java
New file
@@ -0,0 +1,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";
    }
}