From 1571cd0f137ced4345fa8785e166a29dc31b6ad1 Mon Sep 17 00:00:00 2001 From: feiyu02 <risaku@163.com> Date: 星期二, 13 五月 2025 17:42:39 +0800 Subject: [PATCH] 1. 新增动态污染溯源的数据异常判断逻辑 2. 新增动态污染溯源websocket连接功能 --- src/main/kotlin/com/flightfeather/uav/common/utils/MapUtil.kt | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 153 insertions(+), 0 deletions(-) diff --git a/src/main/kotlin/com/flightfeather/uav/common/utils/MapUtil.kt b/src/main/kotlin/com/flightfeather/uav/common/utils/MapUtil.kt index f45b316..cdcfcb9 100644 --- a/src/main/kotlin/com/flightfeather/uav/common/utils/MapUtil.kt +++ b/src/main/kotlin/com/flightfeather/uav/common/utils/MapUtil.kt @@ -1,6 +1,7 @@ package com.flightfeather.uav.common.utils import kotlin.math.PI +import kotlin.math.asin import kotlin.math.cos import kotlin.math.sin @@ -24,4 +25,156 @@ val lat = (dy / ec + pos.second * PI / 180.0) * 180.0 / PI return Pair(lng, lat) } + + /** + * 鑾峰彇涓や釜缁忕含搴︿箣闂寸殑瑙掑害锛�0搴�-360搴︼級 + */ + fun getAngle(lngA: Double, latA: Double, lngB: Double, latB: Double): Double { + val a = ((90 - latB) * Math.PI) / 180; + val b = ((90 - latA) * Math.PI) / 180; + val AOC_BOC = ((lngB - lngA) * Math.PI) / 180; + val cosc = cos(a) * Math.cos(b) + Math.sin(a) * Math.sin(b) * Math.cos(AOC_BOC); + val sinc = Math.sqrt(1 - cosc * cosc); + val sinA = (Math.sin(a) * Math.sin(AOC_BOC)) / sinc; + val A = (Math.asin(sinA) * 180) / Math.PI; + var res = 0.0; + if (lngB > lngA && latB > latA) res = A; + else if (lngB > lngA && latB < latA) res = 180 - A; + else if (lngB < lngA && latB < latA) res = 180 - A; + else if (lngB < lngA && latB > latA) res = 360 + A; + else if (lngB > lngA && latB == latA) res = 90.0; + else if (lngB < lngA && latB == latA) res = 270.0; + else if (lngB == lngA && latB > latA) res = 0.0; + else if (lngB == lngA && latB < latA) res = 180.0; + return res; + } + + /** + * 鑾峰彇涓ょ粡绾害闂寸殑璺濈 + * @return 杩斿洖涓ょ偣闂磋窛绂伙紝鍗曚綅锛氱背 + */ + fun getDistance(lng1: Double, lat1: Double, lng2: Double, lat2: Double): Double { +// lat1 = lat1 || 0; +// lng1 = lng1 || 0; +// lat2 = lat2 || 0; +// lng2 = lng2 || 0; + + val rad1 = (lat1 * Math.PI) / 180.0; + val rad2 = (lat2 * Math.PI) / 180.0; + val a = rad1 - rad2; + val b = (lng1 * Math.PI) / 180.0 - (lng2 * Math.PI) / 180.0; + val distance = + Ea * 2 * asin( + Math.sqrt( + Math.pow( + Math.sin(a / 2), + 2.0 + ) + Math.cos(rad1) * Math.cos(rad2) * Math.pow(Math.sin(b / 2), 2.0) + ) + ); + + return distance; + } + + /** + * 瑙掑害澧炲噺锛岀‘淇濊搴﹀浜�0 - 360搴︿箣闂� + * @param angle 鍘熻搴� + * @param offset 鍋忕Щ閲� + */ + fun plusAngle(angle: Double, offset: Double): Double { + val result = angle + offset; + return if (result > 360) { + result - 360; + } else if (result < 0) { + result + 360; + } else { + result; + } + } + + /** + * 鍒ゆ柇鍧愭爣鐐规槸鍚﹀湪澶氳竟褰㈢殑鍥涜嚦鑼冨洿鍐� + * @param point 鍧愭爣鐐� + * @param polygon 澶氳竟褰㈠潗鏍囩偣鏁扮粍 + */ + fun inBBox(point: Pair<Double, Double>, polygon: List<Pair<Double, Double>>): Boolean { + + val x = point.first + val y = point.second + // 璁$畻澶氳竟褰㈤《鐐圭粡搴﹁寖鍥村拰绾害鑼冨洿 + val xsSort = polygon.map { it.first }.sorted() + val ysSort = polygon.map { it.second }.sorted() + + val xMin = xsSort[0] + val yMin = ysSort[0] + val xMax = xsSort[xsSort.lastIndex] + val yMax = ysSort[ysSort.lastIndex] + + return x >= xMin && x <= xMax && y >= yMin && y <= yMax + } + + /** + * 鍒ゆ柇鍧愭爣鐐规槸鍚﹀湪澶氳竟褰㈢殑杈逛笂 + * @param point 鍧愭爣鐐� + * @param polygon 澶氳竟褰㈠潗鏍囩偣鏁扮粍 + */ + fun onBorder(point: Pair<Double, Double>, polygon: List<Pair<Double, Double>>): Boolean { + var res = false + // 寰幆鍒ゆ柇姣忎竴鏉¤竟 + for (i in polygon.indices) { + val p1 = polygon[i] + val p2 = if (i + 1 == polygon.size) { + polygon[0] + } else { + polygon[i + 1] + } + // 璁$畻杈圭殑涓や釜椤剁偣绾害宸拰缁忓害宸殑姣斿�� + val k1 = (p2.second - p1.second) / (p2.first - p1.first) + // 璁$畻鍧愭爣鐐瑰拰鍏朵腑涓�涓《鐐圭殑绾害宸拰缁忓害宸殑姣斿�� + val k2 = (p2.second - point.second) / (p2.first - point.first) + // 濡傛灉姣斿�肩浉鍚岋紝璇存槑涓変釜鐐瑰湪鍚屼竴鐩寸嚎涓婏紝鍗冲潗鏍囩偣鍦ㄨ竟涓� + if (k1 == k2) { + res = true + break + } + } + return res + } + + /** + * 鍒ゆ柇鍧愭爣鐐规槸鍚﹀湪澶氳竟褰㈠唴閮�(灏勭嚎娉�) + * @param point 鍧愭爣鐐� + * @param polygon 澶氳竟褰㈠潗鏍囩偣鏁扮粍 + */ + fun inPolygon(point: Pair<Double, Double>, polygon: List<Pair<Double, Double>>):Boolean { + val x = point.first + val y = point.second + var j = polygon.size - 1 + var odd = false + for (i in polygon.indices) { + if ( + ((polygon[i].second > y) != (polygon[j].second > y)) + && (x < ((polygon[j].first - polygon[i].first) * (y - polygon[i].second) + / (polygon[j].second - polygon[i].second) + polygon[i].first)) + ) { + odd = !odd; + } + j = i; + } + return odd + } + + /** + * 鍒ゆ柇鍧愭爣鐐规槸鍚﹀湪澶氳竟褰㈠唴閮� + */ + fun isPointInPolygon(point: Pair<Double, Double>, polygon: List<Pair<Double, Double>>): Boolean { + if (polygon.size < 3) throw IllegalArgumentException("not a polygon") + + // 涓嶅湪鍥涜嚦鑼冨洿鍐咃紝鍒欎竴瀹氫笉鍦ㄥ杈瑰舰鍐� + if (!inBBox(point, polygon)) return false + // 鍦ㄥ杈瑰舰杈逛笂锛屼篃璁や负鍦ㄥ杈瑰舰鍐� + if (onBorder(point, polygon)) return true + // 璁$畻鏄惁鍦ㄥ杈瑰舰鍐呴儴 + return inPolygon(point, polygon) + } } \ No newline at end of file -- Gitblit v1.9.3