summaryrefslogtreecommitdiffhomepage
path: root/android/lib/model/src
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson90@gmail.com>2024-02-13 16:21:28 +0100
committerDavid Göransson <david.goransson90@gmail.com>2024-02-15 13:58:29 +0100
commitc6157ee0ce96e4fbb0657bc7cac21c817093461c (patch)
tree09d889154ca5e32367b51a4952b8760371d6da10 /android/lib/model/src
parent34b5e9ed46b436a1fa4a5025aa136b7c88b4ede5 (diff)
downloadmullvadvpn-c6157ee0ce96e4fbb0657bc7cac21c817093461c.tar.xz
mullvadvpn-c6157ee0ce96e4fbb0657bc7cac21c817093461c.zip
Add Latitude, Longitude and LatLong to model
Diffstat (limited to 'android/lib/model/src')
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/LatLong.kt21
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/Latitude.kt55
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/Longitude.kt55
3 files changed, 131 insertions, 0 deletions
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
new file mode 100644
index 0000000000..ae047130e8
--- /dev/null
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/LatLong.kt
@@ -0,0 +1,21 @@
+package net.mullvad.mullvadvpn.model
+
+import kotlin.math.pow
+import kotlin.math.sqrt
+
+data class LatLong(val latitude: Latitude, val longitude: Longitude) {
+
+ fun distanceTo(other: LatLong): Float =
+ sqrt(
+ latitude.distanceTo(other.latitude).pow(2f) +
+ (longitude.distanceTo(other.longitude).pow(2f))
+ )
+
+ operator fun plus(other: LatLong) =
+ LatLong(latitude + other.latitude, longitude + other.longitude)
+
+ operator fun minus(other: LatLong) =
+ LatLong(latitude - other.latitude, longitude - other.longitude)
+}
+
+const val COMPLETE_ANGLE = 360f
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/Latitude.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/Latitude.kt
new file mode 100644
index 0000000000..14c5b66983
--- /dev/null
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/Latitude.kt
@@ -0,0 +1,55 @@
+package net.mullvad.mullvadvpn.model
+
+import kotlin.math.absoluteValue
+
+@JvmInline
+value class Latitude(val value: Float) {
+ init {
+ require(value in LATITUDE_RANGE) {
+ "Latitude: '$value' must be between $MIN_LATITUDE_VALUE and $MAX_LATITUDE_VALUE"
+ }
+ }
+
+ fun distanceTo(other: Latitude) = (other.value - value).absoluteValue
+
+ operator fun plus(other: Latitude) = fromFloat(value + other.value)
+
+ operator fun minus(other: Latitude) = fromFloat(value - other.value)
+
+ companion object {
+ private const val MIN_LATITUDE_VALUE: Float = -90f
+ private const val MAX_LATITUDE_VALUE: Float = 90f
+ private val LATITUDE_RANGE = MIN_LATITUDE_VALUE..MAX_LATITUDE_VALUE
+
+ /**
+ * Create a [Latitude] from a float value.
+ *
+ * This function will unwind a float to a valid latitude value. E.g 190 will be unwound to
+ * -10 and 360 will be unwound to 0.
+ */
+ fun fromFloat(value: Float): Latitude {
+ val unwoundValue = unwind(value)
+ return Latitude(unwoundValue)
+ }
+
+ private fun unwind(value: Float): Float {
+ // Remove all 360 degrees
+ val withoutRotations = value % COMPLETE_ANGLE
+
+ // If we are above 180 or below -180, we wrapped half a turn and need to flip sign
+ val partiallyUnwound =
+ if (withoutRotations.absoluteValue > COMPLETE_ANGLE / 2) {
+ -withoutRotations % (COMPLETE_ANGLE / 2)
+ } else withoutRotations
+
+ return when {
+ partiallyUnwound < MIN_LATITUDE_VALUE ->
+ MIN_LATITUDE_VALUE - (partiallyUnwound % MIN_LATITUDE_VALUE)
+ partiallyUnwound > MAX_LATITUDE_VALUE ->
+ MAX_LATITUDE_VALUE - (partiallyUnwound % MAX_LATITUDE_VALUE)
+ // partiallyUnwound in range MIN_LATITUDE_VALUE..MAX_LATITUDE_VALUE
+ else -> partiallyUnwound
+ }
+ }
+ }
+}
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/Longitude.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/Longitude.kt
new file mode 100644
index 0000000000..9f73a6ff17
--- /dev/null
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/Longitude.kt
@@ -0,0 +1,55 @@
+package net.mullvad.mullvadvpn.model
+
+import kotlin.math.absoluteValue
+
+@JvmInline
+value class Longitude(val value: Float) {
+ init {
+ require(value in LONGITUDE_RANGE) {
+ "Longitude: '$value' must be between $MIN_LONGITUDE_VALUE and $MAX_LONGITUDE_VALUE"
+ }
+ }
+
+ fun distanceTo(other: Longitude) = vectorTo(other).value.absoluteValue
+
+ fun vectorTo(other: Longitude): Longitude {
+ val diff = other.value - value
+ val vectorValue =
+ when {
+ diff > MAX_LONGITUDE_VALUE -> diff - COMPLETE_ANGLE
+ diff < MIN_LONGITUDE_VALUE -> diff + COMPLETE_ANGLE
+ else -> diff
+ }
+ return Longitude(vectorValue)
+ }
+
+ operator fun plus(other: Longitude) = fromFloat(value + other.value)
+
+ operator fun minus(other: Longitude) = fromFloat(value - other.value)
+
+ companion object {
+ private const val MIN_LONGITUDE_VALUE: Float = -180f
+ private const val MAX_LONGITUDE_VALUE: Float = 180f
+ private val LONGITUDE_RANGE = MIN_LONGITUDE_VALUE..MAX_LONGITUDE_VALUE
+
+ /**
+ * Create a [Longitude] from a float value.
+ *
+ * This function will unwind a float to a valid longitude value. E.g 190 will be unwound to
+ * -170 and 360 will be unwound to 0.
+ */
+ fun fromFloat(value: Float): Longitude {
+ val unwoundValue = unwind(value)
+ return Longitude(unwoundValue)
+ }
+
+ private fun unwind(value: Float): Float {
+ val unwound = value % COMPLETE_ANGLE
+ return when {
+ unwound > MAX_LONGITUDE_VALUE -> unwound - COMPLETE_ANGLE
+ unwound < MIN_LONGITUDE_VALUE -> unwound + COMPLETE_ANGLE
+ else -> unwound
+ }
+ }
+ }
+}