From 341a180fde86a2cadefa79e8468b51bbb587aae5 Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Mon, 10 Nov 2025 17:26:45 +0800
Subject: [PATCH] 判断打点是否在禁飞区内或者经过禁飞区
---
ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java | 18 +++++
ard-system/src/main/java/com/ard/data/noflyzone/utils/NoFlyZoneUtils.java | 105 +++++++++++++++++++++++++++++++++++
2 files changed, 122 insertions(+), 1 deletions(-)
diff --git a/ard-system/src/main/java/com/ard/data/noflyzone/utils/NoFlyZoneUtils.java b/ard-system/src/main/java/com/ard/data/noflyzone/utils/NoFlyZoneUtils.java
new file mode 100644
index 0000000..350b3d4
--- /dev/null
+++ b/ard-system/src/main/java/com/ard/data/noflyzone/utils/NoFlyZoneUtils.java
@@ -0,0 +1,105 @@
+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;
+ }
+}
diff --git a/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java b/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java
index 95bf621..311c6c8 100644
--- a/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java
+++ b/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java
@@ -4,6 +4,10 @@
import com.ard.common.core.redis.RedisCache;
import com.ard.common.exception.ServiceException;
import com.ard.common.utils.StringUtils;
+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.aspect.annotation.CheckControlRight;
import com.ard.work.aspect.annotation.CheckTakeoffAltitude;
import com.ard.work.component.forest.TyClient;
@@ -78,8 +82,10 @@
@Resource
private IArdDroneInfoService ardDroneService;
@Resource
+ private IArdNoFlyZoneService ardNoFlyZoneService;
+ @Resource
private TyClient tyClient;
- @Autowired
+ @Resource
private RedisCache redisCache;
/**
@@ -670,6 +676,16 @@
if (!isDroneOnline(boxSn)) {
throw new ServiceException("无人机离线,无法执行指令, boxSn: " + boxSn);
}
+ // 判断目标点是否经过禁飞区
+ List<ArdNoFlyZone> ardNoFlyZones = ardNoFlyZoneService.selectArdNoFlyZoneList(new ArdNoFlyZone());
+ if (!ardNoFlyZones.isEmpty()) {
+ Vertex vertex = new Vertex(flyPointControlDTO.getLongitude(), flyPointControlDTO.getLatitude());
+ boolean inNoFlyZones = NoFlyZoneUtils.isInNoFlyZones(vertex, ardNoFlyZones);
+ if (inNoFlyZones) {
+ throw new ServiceException("目标点在禁飞区内,无法执行指令, boxSn: " + boxSn);
+ }
+ }
+
FlyPointControlCmd flyPointControlCmd = new FlyPointControlCmd(flyPointControlDTO);
this.sendMessage(ardDroneInfo.getServerId(), flyPointControlCmd);
return true;
--
Gitblit v1.9.3