summaryrefslogtreecommitdiffhomepage
path: root/android/lib
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson@mullvad.net>2024-03-20 14:01:03 +0100
committerDavid Göransson <david.goransson@mullvad.net>2024-03-22 10:55:42 +0100
commit9d35783e89d662def96e9848641193ff7a3a7810 (patch)
treeea4095ee769eb7b8d31ccee13dcbccdb0508367c /android/lib
parent585c6533122ca88315d47895bbd3f883ad7edfdf (diff)
downloadmullvadvpn-9d35783e89d662def96e9848641193ff7a3a7810.tar.xz
mullvadvpn-9d35783e89d662def96e9848641193ff7a3a7810.zip
Base animation duration on actual distance estimation
Diffstat (limited to 'android/lib')
-rw-r--r--android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/CameraAnimation.kt10
-rw-r--r--android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/Constants.kt5
-rw-r--r--android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/MapGLRenderer.kt4
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/LatLong.kt29
-rw-r--r--android/lib/model/src/test/kotlin/net/mullvad/mullvadvpn/model/LatLongTest.kt25
5 files changed, 61 insertions, 12 deletions
diff --git a/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/CameraAnimation.kt b/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/CameraAnimation.kt
index 00fcf97ab7..6ce7690bc5 100644
--- a/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/CameraAnimation.kt
+++ b/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/CameraAnimation.kt
@@ -38,8 +38,8 @@ fun animatedCameraPosition(
}
val distance =
- remember(targetCameraLocation) { targetCameraLocation.distanceTo(previousLocation).toInt() }
- val duration = distance.toAnimationDuration()
+ remember(targetCameraLocation) { targetCameraLocation.seppDistanceTo(previousLocation) }
+ val duration = distance.toAnimationDurationMillis()
val longitudeAnimation = remember { Animatable(targetCameraLocation.longitude.value) }
@@ -97,5 +97,7 @@ fun animatedCameraPosition(
)
}
-private fun Int.toAnimationDuration() =
- (this * DISTANCE_DURATION_SCALE_FACTOR).coerceIn(MIN_ANIMATION_MILLIS, MAX_ANIMATION_MILLIS)
+private fun Float.toAnimationDurationMillis(): Int =
+ (this * DISTANCE_DURATION_SCALE_FACTOR)
+ .toInt()
+ .coerceIn(MIN_ANIMATION_MILLIS, MAX_ANIMATION_MILLIS)
diff --git a/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/Constants.kt b/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/Constants.kt
index dfd80d547d..a0aacc34c6 100644
--- a/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/Constants.kt
+++ b/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/Constants.kt
@@ -4,9 +4,10 @@ internal const val VERTEX_COMPONENT_SIZE = 3
internal const val COLOR_COMPONENT_SIZE = 4
internal const val MATRIX_SIZE = 16
-// Constant what will talk the distance in LatLng multiply it to determine the animation duration,
+// Constant what will take the distance in km between two LatLong, multiply it to determine the
+// animation duration,
// the result is then confined to the MIN_ANIMATION_MILLIS and MAX_ANIMATION_MILLIS
-internal const val DISTANCE_DURATION_SCALE_FACTOR = 20
+internal const val DISTANCE_DURATION_SCALE_FACTOR = 0.4f
internal const val MIN_ANIMATION_MILLIS = 1300
internal const val MAX_ANIMATION_MILLIS = 2500
// The cut off where we go from a short animation (camera pans) to a far animation (camera pans +
diff --git a/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/MapGLRenderer.kt b/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/MapGLRenderer.kt
index bf44e5ee14..41ac903fb1 100644
--- a/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/MapGLRenderer.kt
+++ b/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/MapGLRenderer.kt
@@ -13,7 +13,7 @@ import net.mullvad.mullvadvpn.lib.map.data.LocationMarkerColors
import net.mullvad.mullvadvpn.lib.map.data.MapViewState
import net.mullvad.mullvadvpn.lib.map.internal.shapes.Globe
import net.mullvad.mullvadvpn.lib.map.internal.shapes.LocationMarker
-import net.mullvad.mullvadvpn.model.COMPLETE_ANGLE
+import net.mullvad.mullvadvpn.model.toRadians
internal class MapGLRenderer(private val resources: Resources) : GLSurfaceView.Renderer {
@@ -79,8 +79,6 @@ internal class MapGLRenderer(private val resources: Resources) : GLSurfaceView.R
}
}
- private fun Float.toRadians() = this * Math.PI.toFloat() / (COMPLETE_ANGLE / 2)
-
private fun toOffsetY(cameraPosition: CameraPosition): Float {
val percent = cameraPosition.verticalBias
val z = cameraPosition.zoom - 1f
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/LatLong.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/LatLong.kt
index ae047130e8..d6749a16a2 100644
--- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/LatLong.kt
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/LatLong.kt
@@ -1,11 +1,13 @@
package net.mullvad.mullvadvpn.model
+import kotlin.math.cos
import kotlin.math.pow
import kotlin.math.sqrt
+import net.mullvad.mullvadvpn.model.Latitude.Companion.mean
data class LatLong(val latitude: Latitude, val longitude: Longitude) {
- fun distanceTo(other: LatLong): Float =
+ fun degreeDistanceTo(other: LatLong): Float =
sqrt(
latitude.distanceTo(other.latitude).pow(2f) +
(longitude.distanceTo(other.longitude).pow(2f))
@@ -16,6 +18,31 @@ data class LatLong(val latitude: Latitude, val longitude: Longitude) {
operator fun minus(other: LatLong) =
LatLong(latitude - other.latitude, longitude - other.longitude)
+
+ /**
+ * Calculate the distance between two points on the earth's surface using the spherical earth
+ * projected to a plane. ( This method has some drawbacks and shortcomings for extreme values
+ * closer to the Poles but should be good enough for our use case. ) Reference:
+ * https://en.wikipedia.org/wiki/Geographical_distance#Spherical_Earth_projected_to_a_plane
+ *
+ * @param other the other point to calculate the distance to.
+ * @return the estimated distance in kilometers.
+ */
+ fun seppDistanceTo(other: LatLong): Float =
+ EARTH_RADIUS *
+ sqrt(
+ latitude.distanceTo(other.latitude).toRadians().pow(2) +
+ (cos(mean(latitude, other.latitude).value.toRadians()) *
+ longitude.distanceTo(other.longitude).toRadians())
+ .pow(2)
+ )
+
+ companion object {
+ // Average radius of the earth in kilometers
+ const val EARTH_RADIUS = 6371.009f
+ }
}
const val COMPLETE_ANGLE = 360f
+
+fun Float.toRadians() = this * Math.PI.toFloat() / (COMPLETE_ANGLE / 2)
diff --git a/android/lib/model/src/test/kotlin/net/mullvad/mullvadvpn/model/LatLongTest.kt b/android/lib/model/src/test/kotlin/net/mullvad/mullvadvpn/model/LatLongTest.kt
index 6644e25e82..b8608ca55c 100644
--- a/android/lib/model/src/test/kotlin/net/mullvad/mullvadvpn/model/LatLongTest.kt
+++ b/android/lib/model/src/test/kotlin/net/mullvad/mullvadvpn/model/LatLongTest.kt
@@ -2,12 +2,13 @@ package net.mullvad.mullvadvpn.model
import kotlin.math.sqrt
import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
class LatLongTest {
@Test
- fun `distance between two LatLong should be same as hypotenuse`() {
+ fun `degree distance between two LatLong should be same as hypotenuse`() {
val latLong1 = LatLong(Latitude(30f), Longitude(40f))
val latLong2 = LatLong(Latitude(-40f), Longitude(170f))
@@ -15,6 +16,26 @@ class LatLongTest {
val longDiff = latLong1.longitude.distanceTo(latLong2.longitude)
val hypotenuse = sqrt(latDiff * latDiff + longDiff * longDiff)
- assertEquals(hypotenuse, latLong1.distanceTo(latLong2))
+ assertEquals(hypotenuse, latLong1.degreeDistanceTo(latLong2))
+ }
+
+ @Test
+ fun `ensure seppDistance respects lateral value`() {
+ // Malmö & New York is a shorter distance than Malmö & Johannesburg, but the degree
+ // difference is larger since they are at a higher latitude.
+
+ // Malmo 55.6050° N, 13.0038° E
+ val malmo = LatLong(Latitude(55.6050f), Longitude(13.0038f))
+
+ // New York 40.7128° N, 74.0060° W
+ val newYork = LatLong(Latitude(40.7128f), Longitude(-74.0060f))
+
+ // Johannesburg 26.2041° S, 28.0473° E
+ val johannesburg = LatLong(Latitude(-26.2041f), Longitude(28.0473f))
+
+ val malmoToNewYork = malmo.seppDistanceTo(newYork)
+ val malmoToJohannesburg = malmo.seppDistanceTo(johannesburg)
+
+ assertTrue { malmoToNewYork < malmoToJohannesburg }
}
}