Skip to content

Commit

Permalink
feat: Adding PolyUtil extensions to List<LatLng> (#16)
Browse files Browse the repository at this point in the history
* Adding more PolyUtil extensions.

* doc edits

* Remove brackets around this.
  • Loading branch information
arriolac authored Mar 18, 2020
1 parent e72e9cf commit d4cd6f5
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 3 deletions.
58 changes: 55 additions & 3 deletions maps-utils-ktx/src/main/java/com/google/maps/android/ktx/LatLng.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,65 @@
*
*/
@file:Suppress("NOTHING_TO_INLINE")

package com.google.maps.android.ktx

import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.PolyUtil
import com.google.maps.android.SphericalUtil

/**
* Computes whether the given [latLng] lies on or is near this polyline within [tolerance] (in
* meters).
*
* @param latLng the LatLng to inspect
* @param geodesic if this polyline is geodesic or not
* @param tolerance the tolerance in meters
* @return true if [latLng] is on this path, otherwise, false
*
* @see PolyUtil.isLocationOnPath
*/
inline fun List<LatLng>.isLocationOnPath(
latLng: LatLng,
geodesic: Boolean,
tolerance: Double = 0.1
): Boolean = PolyUtil.isLocationOnPath(latLng, this, geodesic, tolerance)

/**
* Checks whether or not [latLng] lies on or is near the edge of this polygon within the [tolerance]
* (in meters). The default value is [PolyUtil.DEFAULT_TOLERANCE].
*
* @param latLng the LatLng to inspect
* @param geodesic if this polygon is geodesic or not
* @param tolerance the tolerance in meters
* @return true if [latLng] lies on or is near the edge of this Polygon, otherwise, false
*
* @see PolyUtil.isLocationOnEdge
*/
inline fun List<LatLng>.isOnEdge(
latLng: LatLng,
geodesic: Boolean,
tolerance: Double = 0.1
): Boolean = PolyUtil.isLocationOnEdge(latLng, this, geodesic, tolerance)

/**
* Computes whether the [latLng] lies inside this.
*
* The polygon is always considered closed, regardless of whether the last point equals
* the first or not.
*
* Inside is defined as not containing the South Pole -- the South Pole is always outside.
* The polygon is formed of great circle segments if [geodesic] is true, and of rhumb
* (loxodromic) segments otherwise.
*
* @param latLng the LatLng to check if it is contained within this polygon
* @param geodesic if this Polygon is geodesic or not
*
* @see PolyUtil.containsLocation
*/
inline fun List<LatLng>.containsLocation(latLng: LatLng, geodesic: Boolean): Boolean =
PolyUtil.containsLocation(latLng, this, geodesic)

/**
* Simplifies this list of LatLng using the Douglas-Peucker decimation. Increasing the value of
* [tolerance] will result in fewer points.
Expand All @@ -30,7 +83,8 @@ import com.google.maps.android.SphericalUtil
*
* @see PolyUtil.simplify
*/
inline fun List<LatLng>.simplify(tolerance: Double): List<LatLng> = PolyUtil.simplify(this, tolerance)
inline fun List<LatLng>.simplify(tolerance: Double): List<LatLng> =
PolyUtil.simplify(this, tolerance)

/**
* Decodes this encoded string into a [LatLng] list.
Expand All @@ -48,7 +102,6 @@ inline fun String.toLatLngList(): List<LatLng> = PolyUtil.decode(this)
* @return the encoded String
*
* @see [Polyline Algorithm Format](https://developers.google.com/maps/documentation/utilities/polylinealgorithm)
*
*/
inline fun List<LatLng>.latLngListEncode(): String = PolyUtil.encode(this)

Expand All @@ -75,7 +128,6 @@ inline fun List<LatLng>.sphericalPathLength(): Double = SphericalUtil.computeLen
*/
inline fun List<LatLng>.sphericalPolygonArea(): Double = SphericalUtil.computeArea(this)


/**
* Computes the signed area under a closed path on Earth. The sign of the area may be used to
* determine the orientation of the path.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,40 @@ class LatLngTest {
1e-6
)
}

@Test
fun `contains location evaluates to true`() {
val latLngList = listOf(LatLng(0.0, 0.0), LatLng(0.0, 90.0), LatLng(-90.0, 45.0))
assertTrue(latLngList.containsLocation(LatLng(30.0, 45.0), geodesic = true))
}

@Test
fun `contains location evaluates to false`() {
val latLngList = listOf(LatLng(0.0, 0.0), LatLng(0.0, 90.0), LatLng(-90.0, 45.0))
assertFalse(latLngList.containsLocation(LatLng(-30.0, 45.0), geodesic = true))
}

@Test
fun `isOnEdge location evaluates to true`() {
val latLngList = listOf(LatLng(0.0, 0.0), LatLng(0.0, 90.0), LatLng(-90.0, 45.0))
assertTrue(latLngList.isOnEdge(LatLng(0.0, 45.0), geodesic = true))
}

@Test
fun `isOnEdge location evaluates to false`() {
val latLngList = listOf(LatLng(0.0, 0.0), LatLng(0.0, 90.0), LatLng(-90.0, 45.0))
assertFalse(latLngList.isOnEdge(LatLng(0.0, -45.0), geodesic = true))
}

@Test
fun `isLocationOnPath location evaluates to true`() {
val latLngList = listOf(LatLng(0.0, 0.0), LatLng(0.0, 90.0), LatLng(0.0, 180.0))
assertTrue(latLngList.isLocationOnPath(LatLng(0.0, 45.0), geodesic = true))
}

@Test
fun `isLocationOnPath location evaluates to false`() {
val latLngList = listOf(LatLng(0.0, 0.0), LatLng(0.0, 90.0), LatLng(0.0, 180.0))
assertFalse(latLngList.isLocationOnPath(LatLng(0.0, -45.0), geodesic = true))
}
}

0 comments on commit d4cd6f5

Please sign in to comment.