@@ -32,6 +32,9 @@ import kotlin.math.sin
3232import kotlin.math.sqrt
3333import kotlin.math.tan
3434
35+ private fun Double.toRadians () = this * (PI / 180.0 )
36+ private fun Double.toDegrees () = this * (180.0 / PI )
37+
3538object SphericalUtil {
3639 /* *
3740 * Returns the heading from one LatLng to another LatLng. Headings are
@@ -42,16 +45,17 @@ object SphericalUtil {
4245 @JvmStatic
4346 fun computeHeading (from : LatLng , to : LatLng ): Double {
4447 // 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 )
5559 }
5660
5761 /* *
@@ -176,29 +180,24 @@ object SphericalUtil {
176180 /* *
177181 * Returns distance on the unit sphere; the arguments are in radians.
178182 */
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))
182185
183186 /* *
184187 * Returns the angle between two LatLngs, in radians. This is the same as the distance
185188 * on the unit sphere.
186189 */
187190 @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+ )
194195
195196 /* *
196197 * Returns the distance between two LatLngs, in meters.
197198 */
198199 @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
202201
203202 /* *
204203 * Returns the length of the given path, in meters, on Earth.
@@ -230,9 +229,7 @@ object SphericalUtil {
230229 * @return The path's area in square meters.
231230 */
232231 @JvmStatic
233- fun computeArea (path : Polygon ): Double {
234- return abs(computeSignedArea(path))
235- }
232+ fun computeArea (path : Polygon ) = abs(computeSignedArea(path))
236233
237234 /* *
238235 * 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 {
243240 * @return The loop's area in square meters.
244241 */
245242 @JvmStatic
246- fun computeSignedArea (path : Polygon ): Double {
247- return computeSignedArea(path, EARTH_RADIUS )
248- }
243+ fun computeSignedArea (path : Polygon ) = computeSignedArea(path, EARTH_RADIUS )
249244
250245 /* *
251246 * Returns the signed area of a closed path on a sphere of given radius.
@@ -260,13 +255,13 @@ object SphericalUtil {
260255 }
261256 var total = 0.0
262257 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( )
265260 // For each edge, accumulate the signed area of the triangle formed by the North Pole
266261 // and that edge ("polar triangle").
267262 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( )
270265 total + = polarTriangleArea(tanLat, lng, prevTanLat, prevLng)
271266 prevTanLat = tanLat
272267 prevLng = lng
0 commit comments