@@ -32,6 +32,9 @@ import kotlin.math.sin
32
32
import kotlin.math.sqrt
33
33
import kotlin.math.tan
34
34
35
+ private fun Double.toRadians () = this * (PI / 180.0 )
36
+ private fun Double.toDegrees () = this * (180.0 / PI )
37
+
35
38
object SphericalUtil {
36
39
/* *
37
40
* Returns the heading from one LatLng to another LatLng. Headings are
@@ -42,16 +45,17 @@ object SphericalUtil {
42
45
@JvmStatic
43
46
fun computeHeading (from : LatLng , to : LatLng ): Double {
44
47
// http://williams.best.vwh.net/avform.htm#Crs
45
- val fromLat = Math .toRadians(from.latitude)
46
- val fromLng = Math .toRadians(from.longitude)
47
- val toLat = Math .toRadians(to.latitude)
48
- val toLng = Math .toRadians(to.longitude)
49
- val dLng = toLng - fromLng
50
- val heading = atan2(
51
- sin(dLng) * cos(toLat),
52
- cos(fromLat) * sin(toLat) - sin(fromLat) * cos(toLat) * cos(dLng)
53
- )
54
- return wrap(Math .toDegrees(heading), - 180.0 , 180.0 )
48
+ val fromLatRad = from.latitude.toRadians()
49
+ val toLatRad = to.latitude.toRadians()
50
+ val deltaLngRad = (to.longitude - from.longitude).toRadians()
51
+
52
+ // Breaking the formula down into Y and X components for atan2().
53
+ val y = sin(deltaLngRad) * cos(toLatRad)
54
+ val x = cos(fromLatRad) * sin(toLatRad) - sin(fromLatRad) * cos(toLatRad) * cos(deltaLngRad)
55
+
56
+ val headingRad = atan2(y, x)
57
+
58
+ return wrap(headingRad.toDegrees(), - 180.0 , 180.0 )
55
59
}
56
60
57
61
/* *
@@ -176,29 +180,24 @@ object SphericalUtil {
176
180
/* *
177
181
* Returns distance on the unit sphere; the arguments are in radians.
178
182
*/
179
- private fun distanceRadians (lat1 : Double , lng1 : Double , lat2 : Double , lng2 : Double ): Double {
180
- return arcHav(havDistance(lat1, lat2, lng1 - lng2))
181
- }
183
+ private fun distanceRadians (lat1 : Double , lng1 : Double , lat2 : Double , lng2 : Double ) =
184
+ arcHav(havDistance(lat1, lat2, lng1 - lng2))
182
185
183
186
/* *
184
187
* Returns the angle between two LatLngs, in radians. This is the same as the distance
185
188
* on the unit sphere.
186
189
*/
187
190
@JvmStatic
188
- fun computeAngleBetween (from : LatLng , to : LatLng ): Double {
189
- return distanceRadians(
190
- Math .toRadians(from.latitude), Math .toRadians(from.longitude),
191
- Math .toRadians(to.latitude), Math .toRadians(to.longitude)
192
- )
193
- }
191
+ fun computeAngleBetween (from : LatLng , to : LatLng ) = distanceRadians(
192
+ from.latitude.toRadians(), from.longitude.toRadians(),
193
+ to.latitude.toRadians(), to.longitude.toRadians()
194
+ )
194
195
195
196
/* *
196
197
* Returns the distance between two LatLngs, in meters.
197
198
*/
198
199
@JvmStatic
199
- fun computeDistanceBetween (from : LatLng , to : LatLng ): Double {
200
- return computeAngleBetween(from, to) * EARTH_RADIUS
201
- }
200
+ fun computeDistanceBetween (from : LatLng , to : LatLng ) = computeAngleBetween(from, to) * EARTH_RADIUS
202
201
203
202
/* *
204
203
* Returns the length of the given path, in meters, on Earth.
@@ -230,9 +229,7 @@ object SphericalUtil {
230
229
* @return The path's area in square meters.
231
230
*/
232
231
@JvmStatic
233
- fun computeArea (path : Polygon ): Double {
234
- return abs(computeSignedArea(path))
235
- }
232
+ fun computeArea (path : Polygon ) = abs(computeSignedArea(path))
236
233
237
234
/* *
238
235
* Returns the signed area of a closed path on Earth. The sign of the area may be used to
@@ -243,9 +240,7 @@ object SphericalUtil {
243
240
* @return The loop's area in square meters.
244
241
*/
245
242
@JvmStatic
246
- fun computeSignedArea (path : Polygon ): Double {
247
- return computeSignedArea(path, EARTH_RADIUS )
248
- }
243
+ fun computeSignedArea (path : Polygon ) = computeSignedArea(path, EARTH_RADIUS )
249
244
250
245
/* *
251
246
* Returns the signed area of a closed path on a sphere of given radius.
@@ -260,13 +255,13 @@ object SphericalUtil {
260
255
}
261
256
var total = 0.0
262
257
val prev = path[size - 1 ]
263
- var prevTanLat = tan((PI / 2 - Math .toRadians( prev.latitude)) / 2 )
264
- var prevLng = Math .toRadians( prev.longitude)
258
+ var prevTanLat = tan((PI / 2 - prev.latitude.toRadians( )) / 2 )
259
+ var prevLng = prev.longitude.toRadians( )
265
260
// For each edge, accumulate the signed area of the triangle formed by the North Pole
266
261
// and that edge ("polar triangle").
267
262
for (point in path) {
268
- val tanLat = tan((PI / 2 - Math .toRadians( point.latitude)) / 2 )
269
- val lng = Math .toRadians( point.longitude)
263
+ val tanLat = tan((PI / 2 - point.latitude.toRadians( )) / 2 )
264
+ val lng = point.longitude.toRadians( )
270
265
total + = polarTriangleArea(tanLat, lng, prevTanLat, prevLng)
271
266
prevTanLat = tanLat
272
267
prevLng = lng
0 commit comments