Skip to content

Commit e1119b3

Browse files
authored
Support altitude interpolation in location component. - MAPSAND-291 (#1478)
* Interpolate altitude in Point, improve performance of navigation simulator. * Add change log. * Add altitude to DefaultLocationProvider. * Update changelog. * Clean up. * Check if altitude exists before interpolating. * Address review comment. * Fix test.
1 parent c23978c commit e1119b3

File tree

7 files changed

+52
-23
lines changed

7 files changed

+52
-23
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Mapbox welcomes participation and contributions from everyone.
88
## Dependencies
99
* Bump telemetry to [v8.1.4](https://github.com/mapbox/mapbox-events-android/releases/tag/telem-8.1.4-core-5.0.2). ([#1484](https://github.com/mapbox/mapbox-maps-android/pull/1484))
1010

11+
#main
12+
## Bug fixes 🐞
13+
* Support altitude interpolation in location component, and pass through GPS altitude information from the DefaultLocationProvider. ([1478](https://github.com/mapbox/mapbox-maps-android/pull/1478))
14+
1115
# 10.7.0-beta.1 June 29, 2022
1216
## Breaking changes ⚠️
1317
* Remove deprecated `FollowPuckViewportStateOptions.animationDurationMs` from experimental viewport plugin. ([1421](https://github.com/mapbox/mapbox-maps-android/pull/1421))

app/src/main/java/com/mapbox/maps/testapp/utils/NavigationSimulator.kt

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ import com.mapbox.maps.plugin.viewport.data.OverviewViewportStateOptions
2525
import com.mapbox.maps.plugin.viewport.data.ViewportOptions
2626
import com.mapbox.maps.plugin.viewport.viewport
2727
import com.mapbox.maps.testapp.R
28-
import com.mapbox.turf.TurfConstants
29-
import com.mapbox.turf.TurfMeasurement
30-
import com.mapbox.turf.TurfMisc
3128

3229
/**
3330
* Simulate a navigation route with pre-defined route as LineString.
@@ -47,8 +44,6 @@ class NavigationSimulator(
4744
private lateinit var routeLayer: LineLayer
4845
private lateinit var casingLayer: LineLayer
4946
private val handler = Handler(Looper.getMainLooper())
50-
private val totalRouteLength = TurfMeasurement.length(routePoints, TurfConstants.UNIT_CENTIMETERS)
51-
private val routeStartPoint = routePoints.coordinates().first()
5247
private val viewportPlugin = mapView.viewport
5348
private val followPuckViewportState =
5449
viewportPlugin.makeFollowPuckViewportState(FollowPuckViewportStateOptions.Builder().build())
@@ -338,12 +333,10 @@ class NavigationSimulator(
338333
}
339334

340335
override fun onIndicatorPositionChanged(point: Point) {
341-
val progress = TurfMeasurement.length(
342-
TurfMisc.lineSlice(routeStartPoint, point, routePoints),
343-
TurfConstants.UNIT_CENTIMETERS
344-
) / totalRouteLength
345-
routeLayer.lineTrimOffset(listOf(0.0, progress))
346-
casingLayer.lineTrimOffset(listOf(0.0, progress))
336+
// use altitude to pass through interpolated progress data, reduce the overhead to
337+
// calculate the progress on each frame.
338+
routeLayer.lineTrimOffset(listOf(0.0, point.altitude()))
339+
casingLayer.lineTrimOffset(listOf(0.0, point.altitude()))
347340
}
348341

349342
fun onDestroy() {

app/src/main/java/com/mapbox/maps/testapp/utils/SimulateRouteLocationProvider.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import com.mapbox.geojson.LineString
66
import com.mapbox.geojson.Point
77
import com.mapbox.maps.plugin.locationcomponent.LocationConsumer
88
import com.mapbox.maps.plugin.locationcomponent.LocationProvider
9+
import com.mapbox.turf.TurfConstants
910
import com.mapbox.turf.TurfMeasurement
11+
import com.mapbox.turf.TurfMisc
1012
import java.util.concurrent.*
1113

1214
/**
@@ -17,6 +19,8 @@ class SimulateRouteLocationProvider(
1719
val route: LineString,
1820
private val handler: Handler = Handler(Looper.getMainLooper())
1921
) : LocationProvider {
22+
private val totalRouteLength = TurfMeasurement.length(route, TurfConstants.UNIT_CENTIMETERS)
23+
private val routeStartPoint = route.coordinates().first()
2024
private val locationConsumers = CopyOnWriteArraySet<LocationConsumer>()
2125
private var isFakeLocationEmitting = false
2226
override fun registerLocationConsumer(locationConsumer: LocationConsumer) {
@@ -44,7 +48,7 @@ class SimulateRouteLocationProvider(
4448
handler.postDelayed(
4549
{
4650
if (iterator.hasNext()) {
47-
val point = iterator.next()
51+
val point = iterator.next().insertProgressInfo()
4852
val bearing = TurfMeasurement.bearing(lastLocation, point)
4953
lastLocation = point
5054
lastBearing = bearing
@@ -61,6 +65,17 @@ class SimulateRouteLocationProvider(
6165
)
6266
}
6367

68+
// use altitude of Point to pass through progress data, and use internal animator to interpolate
69+
// the progress, thus reduce the overhead to calculate the progress on each frame.
70+
private fun Point.insertProgressInfo() = Point.fromLngLat(
71+
longitude(),
72+
latitude(),
73+
TurfMeasurement.length(
74+
TurfMisc.lineSlice(routeStartPoint, this, route),
75+
TurfConstants.UNIT_CENTIMETERS
76+
) / totalRouteLength
77+
)
78+
6479
private companion object {
6580
const val LOCATION_UPDATE_INTERVAL_MS = 1000L
6681
}

plugin-locationcomponent/src/main/java/com/mapbox/maps/plugin/locationcomponent/DefaultLocationProvider.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,14 @@ class DefaultLocationProvider @VisibleForTesting(otherwise = PRIVATE) internal c
7979
}
8080

8181
private fun notifyLocationUpdates(location: Location) {
82+
val locationPoint = if (location.hasAltitude()) {
83+
Point.fromLngLat(location.longitude, location.latitude, location.altitude)
84+
} else {
85+
Point.fromLngLat(location.longitude, location.latitude)
86+
}
87+
8288
locationConsumers.forEach { consumer ->
83-
consumer.onLocationUpdated(Point.fromLngLat(location.longitude, location.latitude))
89+
consumer.onLocationUpdated(locationPoint)
8490
if (currentPuckBearingSource == PuckBearingSource.COURSE) {
8591
consumer.onBearingUpdated(location.bearing.toDouble())
8692
}

plugin-locationcomponent/src/main/java/com/mapbox/maps/plugin/locationcomponent/animators/Evaluators.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@ internal object Evaluators {
88
* Type evaluator for Point data
99
*/
1010
val POINT = TypeEvaluator<Point> { fraction, startValue, endValue ->
11-
Point.fromLngLat(
12-
startValue.longitude() + fraction * (endValue.longitude() - startValue.longitude()),
13-
startValue.latitude() + fraction * (endValue.latitude() - startValue.latitude())
14-
)
11+
val longitude = startValue.longitude() + fraction * (endValue.longitude() - startValue.longitude())
12+
val latitude = startValue.latitude() + fraction * (endValue.latitude() - startValue.latitude())
13+
if (startValue.hasAltitude() && endValue.hasAltitude()) {
14+
Point.fromLngLat(
15+
longitude,
16+
latitude,
17+
startValue.altitude() + fraction * (endValue.altitude() - startValue.altitude()),
18+
)
19+
} else {
20+
Point.fromLngLat(longitude, latitude)
21+
}
1522
}
1623

1724
/**

plugin-locationcomponent/src/test/java/com/mapbox/maps/plugin/locationcomponent/DefaultLocationProviderTest.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,10 @@ class DefaultLocationProviderTest {
175175
val locationEngineResult = mockk<LocationEngineResult>(relaxed = true)
176176
val location = mockk<Location>(relaxed = true)
177177
every { locationEngineResult.lastLocation } returns location
178+
every { location.hasAltitude() } returns true
178179
every { location.longitude } returns 12.0
179180
every { location.latitude } returns 34.0
181+
every { location.altitude } returns 10.0
180182
every { location.bearing } returns 90.0f
181183

182184
defaultLocationProvider.registerLocationConsumer(locationConsumer1)
@@ -189,9 +191,9 @@ class DefaultLocationProviderTest {
189191
)
190192
}
191193
locationEngineCallbackSlot.captured.onSuccess(locationEngineResult)
192-
verify { locationConsumer1.onLocationUpdated(Point.fromLngLat(12.0, 34.0)) }
194+
verify { locationConsumer1.onLocationUpdated(Point.fromLngLat(12.0, 34.0, 10.0)) }
193195
verify { locationConsumer1.onBearingUpdated(90.0) }
194-
verify { locationConsumer2.onLocationUpdated(Point.fromLngLat(12.0, 34.0)) }
196+
verify { locationConsumer2.onLocationUpdated(Point.fromLngLat(12.0, 34.0, 10.0)) }
195197
verify { locationConsumer2.onBearingUpdated(90.0) }
196198
}
197199

@@ -201,8 +203,10 @@ class DefaultLocationProviderTest {
201203
val locationEngineResult = mockk<LocationEngineResult>(relaxed = true)
202204
val location = mockk<Location>(relaxed = true)
203205
every { locationEngineResult.lastLocation } returns location
206+
every { location.hasAltitude() } returns true
204207
every { location.longitude } returns 12.0
205208
every { location.latitude } returns 34.0
209+
every { location.altitude } returns 10.0
206210
every { location.bearing } returns 90.0f
207211

208212
defaultLocationProvider.registerLocationConsumer(locationConsumer1)
@@ -215,9 +219,9 @@ class DefaultLocationProviderTest {
215219
)
216220
}
217221
locationEngineCallbackSlot.captured.onSuccess(locationEngineResult)
218-
verify { locationConsumer1.onLocationUpdated(Point.fromLngLat(12.0, 34.0)) }
222+
verify { locationConsumer1.onLocationUpdated(Point.fromLngLat(12.0, 34.0, 10.0)) }
219223
verify(exactly = 0) { locationConsumer1.onBearingUpdated(90.0) }
220-
verify { locationConsumer2.onLocationUpdated(Point.fromLngLat(12.0, 34.0)) }
224+
verify { locationConsumer2.onLocationUpdated(Point.fromLngLat(12.0, 34.0, 10.0)) }
221225
verify(exactly = 0) { locationConsumer2.onBearingUpdated(90.0) }
222226
defaultLocationProvider.locationCompassListener.onCompassChanged(90.0f)
223227
verify { locationConsumer1.onBearingUpdated(90.0) }

plugin-locationcomponent/src/test/java/com/mapbox/maps/plugin/locationcomponent/LocationIndicatorLayerWrapperTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ class LocationIndicatorLayerWrapperTest {
162162
layer.updateStyle(newStyle)
163163
val radius = 1.0
164164
layer.accuracyRadius(radius)
165-
verify(exactly = 0) { style.setStyleLayerProperty(INDICATOR_LAYER_ID, "accuracy-radius", Value.valueOf(radius)) }
166-
verify(exactly = 1) { newStyle.setStyleLayerProperty(INDICATOR_LAYER_ID, "accuracy-radius", Value.valueOf(radius)) }
165+
verify(exactly = 0) { style.setStyleLayerProperty(INDICATOR_LAYER_ID, "accuracy-radius", any()) }
166+
verify(exactly = 1) { newStyle.setStyleLayerProperty(INDICATOR_LAYER_ID, "accuracy-radius", any()) }
167167
}
168168

169169
companion object {

0 commit comments

Comments
 (0)