Skip to content

Commit 90c56df

Browse files
dkhawkkikoso
andauthored
feat(library): Port PolyUtil to Kotlin and enhance tests (#1565)
* feat: port MathUtil to Kotlin This commit ports the `MathUtil` class from Java to idiomatic Kotlin. The existing tests were leveraged to ensure that the port was successful, and a new test was added for `MathUtil` to ensure that it is well-tested. * feat: port SphericalUtil to Kotlin This commit ports the `SphericalUtil` class from Java to idiomatic Kotlin. The existing tests were leveraged to ensure that the port was successful, and the tests were updated to use Google Truth assertions. * feat(library): Port PolyUtil to Kotlin and enhance tests This commit introduces a significant modernization of the `PolyUtil` class by porting it from Java to idiomatic Kotlin. This change improves the code's conciseness, readability, and null safety. The key changes in this commit are: - **Porting `PolyUtil` to Kotlin**: The `PolyUtil` class has been completely rewritten in Kotlin, taking advantage of features like top-level functions, default arguments, and extension functions. The public API has been preserved with `@JvmStatic` annotations to ensure backward compatibility for Java consumers. - **Updating tests to use Google Truth**: The corresponding `PolyUtilTest` has been updated to use Google Truth assertions. This makes the tests more readable and expressive. * fix: Add correct copyright header * refactor: minor changes to comments and a fix to use the correct Google truth dependency * Update library/src/main/java/com/google/maps/android/MathUtil.kt Co-authored-by: Enrique López-Mañas <[email protected]> --------- Co-authored-by: Enrique López-Mañas <[email protected]>
1 parent 0bb1d34 commit 90c56df

File tree

9 files changed

+1408
-1179
lines changed

9 files changed

+1408
-1179
lines changed

library/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ dependencies {
6868
testImplementation(libs.robolectric)
6969
testImplementation(libs.kxml2)
7070
testImplementation(libs.mockk)
71-
testImplementation (libs.kotlin.test)
71+
testImplementation(libs.kotlin.test)
72+
testImplementation(libs.truth)
7273
implementation(libs.kotlin.stdlib.jdk8)
7374
}
7475

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013 Google Inc.
2+
* Copyright 2023 Google Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -14,25 +14,34 @@
1414
* limitations under the License.
1515
*/
1616

17-
package com.google.maps.android;
17+
package com.google.maps.android
1818

19-
import static java.lang.Math.*;
19+
import kotlin.math.PI
20+
import kotlin.math.asin
21+
import kotlin.math.atan
22+
import kotlin.math.cos
23+
import kotlin.math.exp
24+
import kotlin.math.ln
25+
import kotlin.math.sin
26+
import kotlin.math.sqrt
27+
import kotlin.math.tan
2028

2129
/**
2230
* Utility functions that are used my both PolyUtil and SphericalUtil.
2331
*/
24-
class MathUtil {
32+
object MathUtil {
2533
/**
2634
* The earth's radius, in meters.
2735
* Mean radius as defined by IUGG.
2836
*/
29-
static final double EARTH_RADIUS = 6371009;
37+
const val EARTH_RADIUS = 6_371_009.0
3038

3139
/**
3240
* Restrict x to the range [low, high].
3341
*/
34-
static double clamp(double x, double low, double high) {
35-
return x < low ? low : (x > high ? high : x);
42+
@JvmStatic
43+
fun clamp(x: Double, low: Double, high: Double): Double {
44+
return if (x < low) low else if (x > high) high else x
3645
}
3746

3847
/**
@@ -42,8 +51,9 @@ static double clamp(double x, double low, double high) {
4251
* @param min The minimum.
4352
* @param max The maximum.
4453
*/
45-
static double wrap(double n, double min, double max) {
46-
return (n >= min && n < max) ? n : (mod(n - min, max - min) + min);
54+
@JvmStatic
55+
fun wrap(n: Double, min: Double, max: Double): Double {
56+
return if (n >= min && n < max) n else mod(n - min, max - min) + min
4757
}
4858

4959
/**
@@ -52,65 +62,80 @@ static double wrap(double n, double min, double max) {
5262
* @param x The operand.
5363
* @param m The modulus.
5464
*/
55-
static double mod(double x, double m) {
56-
return ((x % m) + m) % m;
65+
@JvmStatic
66+
fun mod(x: Double, m: Double): Double {
67+
return (x % m + m) % m
5768
}
5869

5970
/**
6071
* Returns mercator Y corresponding to latitude.
6172
* See http://en.wikipedia.org/wiki/Mercator_projection .
6273
*/
63-
static double mercator(double lat) {
64-
return log(tan(lat * 0.5 + PI / 4));
74+
@JvmStatic
75+
fun mercator(lat: Double): Double {
76+
if (lat > Math.PI / 2 - 1e-9) {
77+
return Double.POSITIVE_INFINITY
78+
}
79+
if (lat < -Math.PI / 2 + 1e-9) {
80+
return Double.NEGATIVE_INFINITY
81+
}
82+
return ln(tan(lat * 0.5 + PI / 4))
6583
}
6684

6785
/**
6886
* Returns latitude from mercator Y.
6987
*/
70-
static double inverseMercator(double y) {
71-
return 2 * atan(exp(y)) - PI / 2;
88+
@JvmStatic
89+
fun inverseMercator(y: Double): Double {
90+
return 2 * atan(exp(y)) - PI / 2
7291
}
7392

7493
/**
7594
* Returns haversine(angle-in-radians).
7695
* hav(x) == (1 - cos(x)) / 2 == sin(x / 2)^2.
7796
*/
78-
static double hav(double x) {
79-
double sinHalf = sin(x * 0.5);
80-
return sinHalf * sinHalf;
97+
@JvmStatic
98+
fun hav(x: Double): Double {
99+
val sinHalf = sin(x * 0.5)
100+
return sinHalf * sinHalf
81101
}
82102

83103
/**
84104
* Computes inverse haversine. Has good numerical stability around 0.
85105
* arcHav(x) == acos(1 - 2 * x) == 2 * asin(sqrt(x)).
86106
* The argument must be in [0, 1], and the result is positive.
87107
*/
88-
static double arcHav(double x) {
89-
return 2 * asin(sqrt(x));
108+
@JvmStatic
109+
fun arcHav(x: Double): Double {
110+
return 2 * asin(sqrt(x))
90111
}
91112

92113
// Given h==hav(x), returns sin(abs(x)).
93-
static double sinFromHav(double h) {
94-
return 2 * sqrt(h * (1 - h));
114+
@JvmStatic
115+
fun sinFromHav(h: Double): Double {
116+
return 2 * sqrt(h * (1 - h))
95117
}
96118

97119
// Returns hav(asin(x)).
98-
static double havFromSin(double x) {
99-
double x2 = x * x;
100-
return x2 / (1 + sqrt(1 - x2)) * .5;
120+
@JvmStatic
121+
fun havFromSin(x: Double): Double {
122+
val x2 = x * x
123+
return x2 / (1 + sqrt(1 - x2)) * .5
101124
}
102125

103126
// Returns sin(arcHav(x) + arcHav(y)).
104-
static double sinSumFromHav(double x, double y) {
105-
double a = sqrt(x * (1 - x));
106-
double b = sqrt(y * (1 - y));
107-
return 2 * (a + b - 2 * (a * y + b * x));
127+
@JvmStatic
128+
fun sinSumFromHav(x: Double, y: Double): Double {
129+
val a = sqrt(x * (1 - x))
130+
val b = sqrt(y * (1 - y))
131+
return 2 * (a + b - 2 * (a * y + b * x))
108132
}
109133

110134
/**
111135
* Returns hav() of distance from (lat1, lng1) to (lat2, lng2) on the unit sphere.
112136
*/
113-
static double havDistance(double lat1, double lat2, double dLng) {
114-
return hav(lat1 - lat2) + hav(dLng) * cos(lat1) * cos(lat2);
137+
@JvmStatic
138+
fun havDistance(lat1: Double, lat2: Double, dLng: Double): Double {
139+
return hav(lat1 - lat2) + hav(dLng) * cos(lat1) * cos(lat2)
115140
}
116-
}
141+
}

0 commit comments

Comments
 (0)