package commons.gis import android.location.Location import kotlin.math.atan2 import kotlin.math.cos import kotlin.math.pow import kotlin.math.sin import kotlin.math.sqrt /**基础工具**/ object BasicTools { /** * 计算2点距离 * Android Location 类自带的计算方法 * @return 返回米 */ fun calculateDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Float { val results = FloatArray(1) Location.distanceBetween(lat1, lon1, lat2, lon2, results) return results[0] // 单位:米 } /** * 计算2点距离 * Android Location 类自带的计算方法 * @return 返回结果为:Pair(距离, 初始方位角(起点到终点)) */ fun calculateDistancePair( lat1: Double, lon1: Double, lat2: Double, lon2: Double ): Pair { val results = FloatArray(2) Location.distanceBetween(lat1, lon1, lat2, lon2, results) return Pair(results[0], (results[1] + 360) % 360) // return Pair(results[0], results[1]) } /** * 标准化方位角,确保结果在 0.0° ~ 360.0° 范围内 * @param bearing 原始方位角(可能为负数) * @return 标准化后的方位角 */ private fun normalizeBearing(bearing: Float): Float { // 取模运算处理循环,再处理边界值 var temp = bearing % 360 if (temp < 0) { temp += 360f } return temp } /** * 计算2点距离 * 纯 Java 实现 Haversine 公式(近似计算) * @return 返回米 */ fun calculateHaversineDistance(lng1: Double, lat1: Double, lng2: Double, lat2: Double): Double { val earthRadius = 6371000.0 // 地球半径,单位:米 val lat1 = Math.toRadians(lat1) val lon1 = Math.toRadians(lng1) val lat2 = Math.toRadians(lat2) val lon2 = Math.toRadians(lng2) val dlat = lat2 - lat1 val dlon = lon2 - lon1 val a = sin(dlat / 2).pow(2) + cos(lat1) * cos(lat2) * sin(dlon / 2).pow(2) val c = 2 * atan2(sqrt(a), sqrt(1 - a)) return earthRadius * c } /** * 根据两个坐标点计算航向角 * @param fromLon 起始点经度 * @param fromLat 起始点纬度 * @param toLon 终点经度 * @param toLat 终点纬度 * @return 航向角(度),范围 0-360 */ fun calculateBearing(fromLon: Double, fromLat: Double, toLon: Double, toLat: Double): Double { // 将度转换为弧度 val lat1 = Math.toRadians(fromLat) val lat2 = Math.toRadians(toLat) val deltaLon = Math.toRadians(toLon - fromLon) // 计算航向角 val y = sin(deltaLon) * cos(lat2) val x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLon) val bearing = Math.toDegrees(atan2(y, x)) // 确保航向角在 0-360 度范围内 return (bearing + 360) % 360 } }