liusuyi
2025-11-10 341a180fde86a2cadefa79e8468b51bbb587aae5
判断打点是否在禁飞区内或者经过禁飞区
1 files added
1 files modified
123 ■■■■■ changed files
ard-system/src/main/java/com/ard/data/noflyzone/utils/NoFlyZoneUtils.java 105 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java 18 ●●●●● patch | view | raw | blame | history
ard-system/src/main/java/com/ard/data/noflyzone/utils/NoFlyZoneUtils.java
New file
@@ -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;
    }
}
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;