diff options
| author | Claude <noreply@anthropic.com> | 2026-04-10 22:26:02 +0000 |
|---|---|---|
| committer | Claude <noreply@anthropic.com> | 2026-04-10 22:26:02 +0000 |
| commit | b01a638674a313355664cc387e7da0d77a9c32d0 (patch) | |
| tree | 44eec133a4842e3d2b7fb0af48da635ca899767f /android-app/app/src | |
| parent | d66ed02942849c0f19efaa1caeae14bd0eb1545b (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
Diffstat (limited to 'android-app/app/src')
| -rw-r--r-- | android-app/app/src/main/kotlin/org/terst/nav/ui/MapHandler.kt | 21 |
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) } /** |
