package commons.gis /** * 利用方位角+距离判断是否经过目标点位的工具类 */ object PassThroughDetector { // 距离阈值:可根据场景调整(步行50米,驾车200米) private val distanceThresholdM: Float = 100.0f // 方位角变化阈值:允许的误差范围 private val bearingThresholdDeg: Float = 15.0f private var speedThresholdMps: Float = 1.0f // 速度阈值(米/秒),1m/s ≈ 3.6km/h // 记录上一次的方位角(-1 表示首次调用) private var lastBearingToTarget: Float = -1f // 记录是否曾接近目标点(距离≤阈值) private var isApproached: Boolean = false /** * 判断是否经过目标点位 * @param currentLat 当前位置纬度 * @param currentLng 当前位置经度 * @param targetLat 目标点纬度 * @param targetLng 目标点经度 * @return true=已经过,false=未经过 */ fun isPassThroughTarget( currentLat: Double, currentLng: Double, targetLat: Double, targetLng: Double ): Boolean { /* * 速度过滤:低于阈值直接返回false,不更新任何状态 * 驾车 5.0 ~ 10.0 换算(km/h) 18 ~ 36 过滤停车 / 堵车状态 * * */ /* if (currentSpeed < speedThresholdMps) { return false }*/ // 1. 计算当前位置到目标点的距离和方位角 var (distanceToTarget, currentBearingToTarget) = BasicTools.calculateDistancePair( currentLat, currentLng, targetLat, targetLng, ) // currentBearingToTarget= normalizeBearing(currentBearingToTarget) // 2. 判断是否接近目标点 if (distanceToTarget <= distanceThresholdM) { isApproached = true } // 3. 首次调用:记录初始方位角,返回未经过 if (lastBearingToTarget == -1f) { lastBearingToTarget = currentBearingToTarget return false } // 4. 计算方位角变化(处理360°循环) var bearingDiff = Math.abs(currentBearingToTarget - lastBearingToTarget) // bearingDiff = Math.min(bearingDiff, 360 - bearingDiff) // println("距离: ${distanceToTarget}米 初始方位角: ${currentBearingToTarget} 方位角变化${bearingDiff}") // 核心判断:曾接近 + 方位角突变≈180° → 判定经过 val isPassThrough = if (isApproached && bearingDiff >= (180 - bearingThresholdDeg) // && bearingDiff <= (180 + bearingThresholdDeg) ) { reset() // 重置状态避免重复判定 true } else { false } // 5. 更新上一次的方位角 lastBearingToTarget = currentBearingToTarget return isPassThrough } /** * 标准化方位角为 0~360°(处理负数) */ private fun normalizeBearing(bearing: Float): Float { var normalizedBearing = bearing % 360 if (normalizedBearing < 0) { normalizedBearing += 360 } return normalizedBearing } /** * 重置检测器状态(开始新的判断时调用) */ fun reset() { lastBearingToTarget = -1f isApproached = false } }