summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-04-10 22:26:02 +0000
committerClaude <noreply@anthropic.com>2026-04-10 22:26:02 +0000
commitb01a638674a313355664cc387e7da0d77a9c32d0 (patch)
tree44eec133a4842e3d2b7fb0af48da635ca899767f
parentd66ed02942849c0f19efaa1caeae14bd0eb1545b (diff)
Suppress map label flicker from GPS jitter
GPS settling produces many tiny position updates that each triggered a 1-second animateCamera(), forcing continuous symbol-collision recalculation and label fade cycles. Fix: skip animation entirely (moveCamera) when the new position is < 3 m from the last one; use a shorter easeCamera(400 ms) for real movement so the animation window is smaller. https://claude.ai/code/session_01HXPjBsogsJVRwCiekDGkJX
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/ui/MapHandler.kt21
1 files changed, 20 insertions, 1 deletions
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/ui/MapHandler.kt b/android-app/app/src/main/kotlin/org/terst/nav/ui/MapHandler.kt
index ca146b1..a7d746f 100644
--- a/android-app/app/src/main/kotlin/org/terst/nav/ui/MapHandler.kt
+++ b/android-app/app/src/main/kotlin/org/terst/nav/ui/MapHandler.kt
@@ -26,6 +26,7 @@ import org.terst.nav.data.model.WindArrow
import org.terst.nav.track.TrackPoint
import kotlin.math.cos
import kotlin.math.sin
+import kotlin.math.sqrt
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -225,14 +226,32 @@ class MapHandler(private val maplibreMap: MapLibreMap) {
* Centers the map on the specified location.
*/
fun centerOnLocation(lat: Double, lon: Double, zoom: Double = 14.0) {
+ val prevLat = lastLat
+ val prevLon = lastLon
lastLat = lat
lastLon = lon
if (!_isFollowing.value) return
+
val position = CameraPosition.Builder()
.target(LatLng(lat, lon))
.zoom(zoom)
.build()
- maplibreMap.animateCamera(CameraUpdateFactory.newCameraPosition(position), 1000)
+
+ // Skip animation for tiny GPS jitter (< 3 m) to avoid repeated symbol
+ // collision recalculations that cause labels to flash on/off.
+ val deltaMeters = approximateMeters(prevLat, prevLon, lat, lon)
+ if (deltaMeters < 3.0) {
+ maplibreMap.moveCamera(CameraUpdateFactory.newCameraPosition(position))
+ } else {
+ maplibreMap.easeCamera(CameraUpdateFactory.newCameraPosition(position), 400)
+ }
+ }
+
+ /** Fast flat-earth distance approximation (accurate to ~0.1% within a few km). */
+ private fun approximateMeters(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double {
+ val dLat = (lat2 - lat1) * 111_320.0
+ val dLon = (lon2 - lon1) * 111_320.0 * cos(Math.toRadians((lat1 + lat2) / 2.0))
+ return sqrt(dLat * dLat + dLon * dLon)
}
/**