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";
|
}
|
|
|
|
}
|