Sorry, you need to enable JavaScript to visit this website.

Map Driving Extension

Map Driving Extension

This module is built on top of the Maps SDK for Android and contains logic and helpful utils that can be used in more complex scenarios, like driving or cycling.

To use this library, add the following dependency to the build.gradle file:

implementation("com.tomtom.online:sdk-maps-driving-extensions:2.4807")
Map and route matching

Map matching snaps an inaccurate GPS probe to the road network obtained from map tiles so roads are represented by collections of coordinates. Route matching is a special case of map matching which snaps an inaccurate GPS probe to the given route. The reference route is represented by a collection of coordinates. The route can be calculated using the Routing API or provided manually.

Sample use case: You have a speed radar application that is used when driving. To have a proper user experience, you want to match GPS positions with the road data obtained from map tiles.

Sample use case: You want to match/place the chevron with the right road.

Sample use case: A user plans and displays a route on the map in your app. The vehicle position is being matched along the planned route.

First you need to create a proper MatchingDataProvider based on your use case.

To create the MatchingDataProvider from a route:

_

MatchingDataProvider routeMatchingProvider = LatLngTraceMatchingDataProvider.fromPoints(getFirstRouteFromMap());
val routeMatchingProvider = LatLngTraceMatchingDataProvider.fromPoints(routes.first().getCoordinates())

To create the MatchingDataProvider for map matcher:

_

MatchingDataProvider matchingDataProvider = tomtomMap.asMatchingDataProvider();
return tomtomMap.asMatchingDataProvider()

After you obtain the MatchingDataProvider, you can create and register matcher in the following manner:

_

matcher = MatcherFactory.createMatcher(matchingDataProvider);
matcher.setMatcherListener(matcherListener);
val matcher = MatcherFactory.createMatcher(matchingDataProvider)
matcher.setMatcherListener(this)

It is important to remove the matcher instance if it is not going to be used. Otherwise memory leaks may occur:

_

matcher.dispose();
matcher.dispose()

To update map matcher with a new GPS position:

_

matcher.match(location);
matcher.match(location)

To process map matcher results:

_

@Override
public void onMatched(MatchResult matchResult) {
    ChevronPosition chevronPosition = new ChevronPosition.Builder(matchResult.getMatchedLocation()).build();

    chevron.setDimmed(!matchResult.isMatched());
    chevron.setPosition(chevronPosition);
    chevron.show();

    tomtomMap.getOverlaySettings().removeOverlays();
    tomtomMap.getOverlaySettings().addOverlay(
            CircleBuilder.create()
                    .position(new LatLng(matchResult.originalLocation))
                    .fill(GPS_DOT_FILL)
                    .color(GPS_DOT_COLOR)
                    .radius(GPS_DOT_RADIUS)
                    .build()
    );
}
val chevronPosition = ChevronPosition.Builder(it.matchedLocation).build()
chevron.isDimmed = it.isDimmed
chevron.position = chevronPosition
chevron.show()
showOriginalLocationDot(it)

Follow the chevron

Allow your users to follow their changing positions on the map e.g., when driving. When a new location is set, the animation moves the chevron to the new position.

Sample use case 1: You want to show your user position when driving.

Custom chevron indicator

You can set a custom icon for the chevron indicator.

To create a custom chevron:

_

ChevronBuilder chevronBuilder = ChevronBuilder.create(activeIcon, inactiveIcon);
chevron = tomtomMap.getDrivingSettings().addChevron(chevronBuilder);
val chevronBuilder = ChevronBuilder.create(activeIcon, inactiveIcon)
chevron = tomtomMap.drivingSettings.addChevron(chevronBuilder)

Chevron tracking mode

Additionally, it is possible to track the chevron. This means that the camera/map and the chevron move when a new location is received so that the map is always centered on the chevron with the bearing of the drive. In the tracking mode, rotate and pan gestures are blocked. The user can only change the zoom level, while the map camera is automatically adjusted to follow the chevron.

To start tracking a selected chevron:

_

tomtomMap.getDrivingSettings().startTracking(getChevron());
tomtomMap.drivingSettings.startTracking(chevron)

To stop tracking a selected chevron:

_

tomtomMap.getDrivingSettings().stopTracking();
tomtomMap.drivingSettings.stopTracking()

You can set the chevron position on the map when in tracking mode.

To change the position:

tomtomMap.drivingSettings.setChevronScreenPosition(ChevronScreenPosition(0.5, 0.75))

To reset/center the position of a chevron:

tomtomMap.drivingSettings.centerChevronScreenPosition()

Update chevron location

To update the chevron base on a GPS position, you need to register to location updates. You can register LocationUpdateListener on the TomTomMap instance. After receiving the new location, you can update the position of the chevron. Use this code snippet:

val listener = LocationUpdateListener { location ->
    chevron.position = ChevronPosition.Builder(location).build()
    chevron.show()
}
tomtomMap.addLocationUpdateListener(listener)

Remember to unregister the listener:

tomtomMap.removeLocationUpdateListener(listener)
image

Chevron overview

image

Chevron tracking

Zooming the route

Zooming in and out are used to navigate through map areas that are too large or too small to be conveniently displayed within a single window. While following the chevron, zooming alters the map scale because it changes the proportion of the workspace shown in each window.

Sample use case: You are a taxi driver navigating through the city of Łódź, and thanks to the zoom level adjusted to the velocity of your car you see a convenient map area for you to move.

Use the following code snippets to try this in your app:

fun setupLocationUpdateListener(tomtomMap: TomtomMap) {
    tomtomMap.addLocationUpdateListener { location ->
        updateZoomLevelBaseOnNewLocation(tomtomMap, location)
    }
}

private fun updateZoomLevelBaseOnNewLocation(tomtomMap: TomtomMap, location: Location) {
    val zoomLevel = when (location.speed) {
        in SMALL_SPEED_RANGE_IN_KMH -> SMALL_SPEED_ZOOM_LEVEL
        in MEDIUM_SPEED_RANGE_IN_KMH -> MEDIUM_SPEED_ZOOM_LEVEL
        in GREATER_SPEED_RANGE_IN_KMH -> GREATER_SPEED_ZOOM_LEVEL
        in BIG_SPEED_RANGE_IN_KMH -> BIG_SPEED_ZOOM_LEVEL
        in HUGE_SPEED_RANGE_IN_KMH -> HUGE_SPEED_ZOOM_LEVEL
        else -> tomtomMap.zoomLevel
    }
    if (tomtomMap.zoomLevel != zoomLevel) {
        setCameraPosition(tomtomMap, zoomLevel = zoomLevel)
    }
}

private fun setCameraPosition(tomtomMap: TomtomMap, zoomLevel: Double) {
    if (!isZooming) {
        isZooming = true
        tomtomMap.centerOn(
            CameraPosition.builder()
                .zoom(zoomLevel)
                .animationDuration(ZOOM_CHANGE_ANIMATION_MILLIS)
                .build(),
            onMapCenteredCallback
        )
    }
}

private val onMapCenteredCallback = object : OnMapCenteredCallback {
    override fun onFinish() {
        isZooming = false
    }

    override fun onCancel() {
        isZooming = false
    }
}

Lookup for the constants used in the sample code:

private const val EXAMPLE_START_ZOOM_LEVEL = 19.0
private const val ZOOM_CHANGE_ANIMATION_MILLIS = 300
private const val SMALL_SPEED_ZOOM_LEVEL = 19.0
private const val MEDIUM_SPEED_ZOOM_LEVEL = 18.0
private const val GREATER_SPEED_ZOOM_LEVEL = 17.0
private const val BIG_SPEED_ZOOM_LEVEL = 16.0
private const val HUGE_SPEED_ZOOM_LEVEL = 14.0
private val SMALL_SPEED_RANGE_IN_KMH = 0.0..10.0
private val MEDIUM_SPEED_RANGE_IN_KMH = 10.0..20.0
private val GREATER_SPEED_RANGE_IN_KMH = 20.0..40.0
private val BIG_SPEED_RANGE_IN_KMH = 40.0..70.0
private val HUGE_SPEED_RANGE_IN_KMH = 70.0..120.0

Screen shots presenting how the programmatic zooming functionality works:

Driving ZoomLevel

Progress along the route

Allow your users to visually distinguish the part of the route that has already been traveled. When a new location is set, the specified route style layer is drawn up to the desired location.

Sample use case: You want to show your user the part of the route that has already been traveled.

Use the following code snippet to create your route progress style:

val style = RouteLayerStyle.Builder()
    .color(DARK_BLUE)
    .build()

Use the following code snippet to activate showing the route progress layer on top of a route:

routeSettings.activateProgressAlongRoute(routeId, style)

Use the following code snippet to update the already traveled part of the route:

routeSettings.updateProgressAlongRoute(routeId, location)

Screen shots presenting how progress along the route works:

image
image