From 145e705946adf1e47512f2450e8bdd42662751e6 Mon Sep 17 00:00:00 2001
From: zhaowenyu <35589726@qq.com>
Date: Sat, 13 Dec 2025 09:38:26 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev

---
 ard-system/src/main/java/com/ard/data/noflyzone/utils/NoFlyZoneUtils.java |   66 ++++++++++++++++++---------------
 1 files changed, 36 insertions(+), 30 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
index b78f29b..26fc38f 100644
--- 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
@@ -17,7 +17,7 @@
 
 
     /**
-     * 计算点到多边形的最近距离
+     * 计算点到多边形的最近距离(米)
      */
     public static double pointToPolygonDistance(Vertex point, List<Vertex> polygon) {
 
@@ -33,7 +33,7 @@
             Vertex a = polygon.get(i);
             Vertex b = polygon.get((i + 1) % n); // 下一点,最后一条边连接第一个点
 
-            double dist = pointToSegmentDistance(point, a, b);
+            double dist = pointToSegmentDistanceHaversine(point, a, b);
             minDistance = Math.min(minDistance, dist);
         }
 
@@ -41,45 +41,51 @@
     }
 
     /**
-     * 计算点到线段的距离
+     * 计算点到线段的距离(米)使用Haversine公式
      */
-    public static double pointToSegmentDistance(Vertex p, Vertex a, Vertex b) {
-        double x = p.x, y = p.y;
-        double x1 = a.x, y1 = a.y;
-        double x2 = b.x, y2 = b.y;
+    public static double pointToSegmentDistanceHaversine(Vertex p, Vertex a, Vertex b) {
+        // 将经纬度换算成以 p 点为参考的局部平面米坐标
+        double[] pa = latLonToXY(a, p.y, p.x);
+        double[] pb = latLonToXY(b, p.y, p.x);
+        double[] pp = latLonToXY(p, p.y, p.x);
 
-        double dx = x2 - x1;
-        double dy = y2 - y1;
+        double dx = pb[0] - pa[0];
+        double dy = pb[1] - pa[1];
 
-        if (dx == 0 && dy == 0) {
-            // A 和 B 是同一个点
-            dx = x - x1;
-            dy = y - y1;
-            return Math.sqrt(dx * dx + dy * dy);
-        }
+        double t = ((pp[0] - pa[0]) * dx + (pp[1] - pa[1]) * dy) / (dx * dx + dy * dy);
 
-        // 投影参数 t(0-1之间表示在线段内部)
-        double t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy);
-
+        double nearestX, nearestY;
         if (t < 0) {
-            // 最近点是 A
-            dx = x - x1;
-            dy = y - y1;
+            nearestX = pa[0];
+            nearestY = pa[1];
         } else if (t > 1) {
-            // 最近点是 B
-            dx = x - x2;
-            dy = y - y2;
+            nearestX = pb[0];
+            nearestY = pb[1];
         } else {
-            // 最近点在线段中间
-            double projX = x1 + t * dx;
-            double projY = y1 + t * dy;
-            dx = x - projX;
-            dy = y - projY;
+            nearestX = pa[0] + t * dx;
+            nearestY = pa[1] + t * dy;
         }
 
-        return Math.sqrt(dx * dx + dy * dy);
+        double distX = pp[0] - nearestX;
+        double distY = pp[1] - nearestY;
+
+        return Math.sqrt(distX * distX + distY * distY);
     }
 
+    /**
+     * 将经纬度转换为局部平面坐标(米)
+     * originLat、originLon 是参考点,经纬度转换到以参考点为原点的平面坐标
+     */
+    public static double[] latLonToXY(Vertex point, double originLat, double originLon) {
+        double R = 6371000; // 地球半径,单位米
+        double dLat = Math.toRadians(point.y - originLat);
+        double dLon = Math.toRadians(point.x - originLon);
+        double x = R * dLon * Math.cos(Math.toRadians(originLat));
+        double y = R * dLat;
+        return new double[]{x, y};
+    }
+
+
 
     /**
      * 判断点是否在多边形内(射线法)

--
Gitblit v1.9.3