feiyu02
2025-09-30 94fee0b511279679b43e210878d3d36e5a14384b
src/main/kotlin/com/flightfeather/uav/common/utils/MapUtil.kt
@@ -1,14 +1,15 @@
package com.flightfeather.uav.common.utils
import kotlin.math.PI
import kotlin.math.asin
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.*
object MapUtil {
    private const val Ea = 6378137 //赤道半径
    private const val Eb = 6356725 //极半径
    // 坐标转换参数
    const val a = 6378245.0; //长半轴
    const val ee = 0.00669342162296594323; //扁率/*** GCJ02 转换为 WGS84* @param lng* @param lat* @returns {*[]}*/
    /**
     * 根据坐标点、距离和角度,获取另一个坐标
@@ -93,6 +94,24 @@
    }
    /**
     * 计算多边形的四至范围
     * @param polygon 多边形坐标点数组
     * @return 四至范围,顺序为最小经度,最大经度, 最小纬度,最大纬度
     */
    fun calFourBoundaries(polygon: List<Pair<Double, Double>>): List<Double> {
        // 计算多边形顶点经度范围和纬度范围
        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 listOf(xMin, xMax, yMin, yMax)
    }
    /**
     * 判断坐标点是否在多边形的四至范围内
     * @param point 坐标点
     * @param polygon 多边形坐标点数组
@@ -102,13 +121,19 @@
        val x = point.first
        val y = point.second
        // 计算多边形顶点经度范围和纬度范围
        val xsSort = polygon.map { it.first }.sorted()
        val ysSort = polygon.map { it.second }.sorted()
        val fb = calFourBoundaries(polygon)
//        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]
        val xMin = xsSort[0]
        val yMin = ysSort[0]
        val xMax = xsSort[xsSort.lastIndex]
        val yMax = ysSort[ysSort.lastIndex]
        val xMin = fb[0]
        val xMax = fb[1]
        val yMin = fb[2]
        val yMax = fb[3]
        return x >= xMin && x <= xMax && y >= yMin && y <= yMax
    }
@@ -146,7 +171,7 @@
     * @param point 坐标点
     * @param polygon 多边形坐标点数组
     */
    fun inPolygon(point: Pair<Double, Double>, polygon: List<Pair<Double, Double>>):Boolean {
    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
@@ -177,4 +202,90 @@
        // 计算是否在多边形内部
        return inPolygon(point, polygon)
    }
    /**
     * 判断经纬度是否在国内
     * @return true: 经纬度不在国内,false:经纬度在国内
     */
    fun outOfChina(point: Pair<Double, Double>): Boolean {
        val lng = point.first
        val lat = point.second
        return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55)
    }
    private fun transformLat(point: Pair<Double, Double>): Double {
        val lng = point.first
        val lat = point.second
        var ret = -100.0 +
                2.0 * lng +
                3.0 * lat +
                0.2 * lat * lat +
                0.1 * lng * lat +
                0.2 * sqrt(abs(lng))
        ret += ((20.0 * sin(6.0 * lng * PI) + 20.0 * sin(2.0 * lng * PI)) * 2.0) / 3.0
        ret += ((20.0 * sin(lat * PI) + 40.0 * sin((lat / 3.0) * PI)) * 2.0) / 3.0
        ret += ((160.0 * sin((lat / 12.0) * PI) + 320 * sin((lat * PI) / 30.0)) * 2.0) / 3.0
        return ret;
    }
    private fun transformLng(point: Pair<Double, Double>): Double {
        val lng = point.first
        val lat = point.second
        var ret = 300.0 +
                lng +
                2.0 * lat +
                0.1 * lng * lng +
                0.1 * lng * lat +
                0.1 * sqrt(abs(lng));
        ret += ((20.0 * sin(6.0 * lng * PI) + 20.0 * sin(2.0 * lng * PI)) * 2.0) / 3.0;
        ret += ((20.0 * sin(lng * PI) + 40.0 * sin((lng / 3.0) * PI)) * 2.0) / 3.0;
        ret += ((150.0 * sin((lng / 12.0) * PI) + 300.0 * sin((lng / 30.0) * PI)) * 2.0) / 3.0
        return ret;
    }
    /**
     * 火星坐标系转WGS84坐标系
     */
    fun gcj02ToWgs84(point: Pair<Double, Double>): Pair<Double, Double> {
        if (outOfChina(point)) {
            return point;
        } else {
            val lng = point.first
            val lat = point.second
            var dlat = transformLat(lng - 105.0 to lat - 35.0);
            var dlng = transformLng(lng - 105.0 to lat - 35.0);
            val radlat = (lat / 180.0) * PI;
            var magic = sin(radlat);
            magic = 1 - ee * magic * magic;
            val sqrtmagic = sqrt(magic);
            dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI);
            dlng = (dlng * 180.0) / ((a / sqrtmagic) * cos(radlat) * PI);
            val mglat = Math.round((lat * 2 - lat - dlat) * 1000000).toDouble() / 1000000;
            val mglng = Math.round((lng * 2 - lng - dlng) * 1000000).toDouble() / 1000000;
            return mglng to mglat
        }
    }
    /**
     * WGS84坐标系转火星坐标系
     */
    fun wgs84ToGcj02(point: Pair<Double, Double>): Pair<Double, Double> {
        if (outOfChina(point)) {
            return point
        } else {
            val lng = point.first
            val lat = point.second
            var dLat = transformLat(lng - 105.0 to lat - 35.0);
            var dLon = transformLng(lng - 105.0 to lat - 35.0);
            val radLat = (lat / 180.0) * PI;
            var magic = sin(radLat);
            magic = 1 - ee * magic * magic;
            val sqrtMagic = sqrt(magic);
            dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * PI);
            dLon = (dLon * 180.0) / ((a / sqrtMagic) * cos(radLat) * PI);
            val mgLat = lat + dLat;
            val mgLon = lng + dLon;
            return mgLon to mgLat
        }
    }
}