package com.ard.data.noflyzone.utils;
|
|
import com.ard.data.noflyzone.domain.ArdNoFlyBox;
|
import com.ard.data.noflyzone.domain.ArdNoFlyZone;
|
import com.ard.data.noflyzone.domain.Vertex;
|
|
import java.util.List;
|
|
public class NoFlyZoneUtils {
|
|
/**
|
* 判断点是否在禁飞区集合中
|
*
|
* @param point 目标点
|
* @param zones 禁飞区集合
|
* @return true: 点在任意禁飞区内
|
*/
|
public static boolean isInNoFlyZones(Vertex point, List<ArdNoFlyZone> zones) {
|
if (point == null || zones == null || zones.isEmpty()) {
|
return false;
|
}
|
|
for (ArdNoFlyZone zone : zones) {
|
// 1️⃣ 先快速判断外接矩形
|
if (zone.getArdNoFlyBox() != null &&
|
!isInBox(point, zone.getArdNoFlyBox())) {
|
continue; // 点不在外接矩形内,跳过
|
}
|
|
// 2️⃣ 多边形判断
|
List<Vertex> vertices = zone.getVertices();
|
if (vertices != null && !vertices.isEmpty()) {
|
if (isPointInPolygon(point, vertices)) {
|
return true;
|
}
|
}
|
}
|
return false;
|
}
|
|
/**
|
* 判断点是否在矩形框内
|
*/
|
private static boolean isInBox(Vertex point, ArdNoFlyBox box) {
|
return point.x >= box.getMinx() && point.x <= box.getMaxx() &&
|
point.y >= box.getMiny() && point.y <= box.getMaxy();
|
}
|
|
/**
|
* 射线法判断点是否在多边形内
|
*/
|
private static boolean isPointInPolygon(Vertex point, List<Vertex> vertices) {
|
if (point == null || vertices == null || vertices.size() < 3) {
|
return false;
|
}
|
|
int count = 0;
|
int n = vertices.size();
|
double epsilon = 1e-9;
|
|
for (int i = 0; i < n; i++) {
|
Vertex v1 = vertices.get(i);
|
Vertex v2 = vertices.get((i + 1) % n);
|
|
// 点就是顶点
|
if (v1.IsSame(point)) {
|
return true;
|
}
|
|
double minX = Math.min(v1.x, v2.x);
|
double maxX = Math.max(v1.x, v2.x);
|
double minY = Math.min(v1.y, v2.y);
|
double maxY = Math.max(v1.y, v2.y);
|
|
// 水平线段
|
if (Math.abs(minY - maxY) < epsilon) {
|
if (Math.abs(point.y - minY) < epsilon && point.x >= minX && point.x <= maxX) {
|
return true;
|
} else {
|
continue;
|
}
|
}
|
|
// 点不在纵向范围
|
if (point.y < minY || point.y > maxY) {
|
continue;
|
}
|
|
double xIntersect = v1.x + (point.y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y);
|
|
if (Math.abs(xIntersect - point.x) < epsilon) {
|
return true; // 点在边界
|
}
|
if (xIntersect > point.x) {
|
count++;
|
}
|
|
if (Math.abs(point.y - minY) < epsilon) {
|
count--;
|
}
|
}
|
|
return count % 2 != 0;
|
}
|
}
|