Routing | Mobile SDK | Urbi Documentation
Android SDK

Routing

To create a route on the map, you need to create two objects: TrafficRouter to find an optimal route and a RouteMapObjectSource data source to display the route on the map.

To find a route between two points, call the findRoute() method and specify the coordinates of the start and end points as RouteSearchPoint objects. You can additionally specify a list of intermediate points of the route and RouteOptions.

val startSearchPoint = RouteSearchPoint(
    coordinates = GeoPoint(latitude = 55.759909, longitude = 37.618806)
)
val finishSearchPoint = RouteSearchPoint(
    coordinates = GeoPoint(latitude = 55.752425, longitude = 37.613983)
)

val trafficRouter = TrafficRouter(sdkContext)
val routesFuture = trafficRouter.findRoute(startSearchPoint, finishSearchPoint)

The findRoute() call will return a deferred result with a list of TrafficRoute objects. To display the found route on the map, you need to use these objects to create RouteMapObject objects and add them to a RouteMapObjectSource data source.

// Create a data source
val routeMapObjectSource = RouteMapObjectSource(sdkContext, RouteVisualizationType.NORMAL)
map.addSource(routeMapObjectSource)

// Find a route
val routesFuture = trafficRouter.findRoute(startSearchPoint, finishSearchPoint)
val trafficRouter = TrafficRouter(sdkContext)

// After receiving the route, add it to the map
routesFuture.onResult { routes: List<TrafficRoute> ->
    var isActive = true
    var routeIndex = 0
    for (route in routes) {
        routeMapObjectSource.addObject(
            RouteMapObject(route, isActive, routeIndex)
        )
        isActive = false
        routeIndex++
    }
}

Instead of using TrafficRouter and RouteMapObjectSource objects and manually processing a list of TrafficRoute objects, you can use RouteEditor and RouteEditorSource. In that case, you can simply pass the coordinates for the route as a RouteParams object to the setRouteParams() method and the route will be displayed automatically.

val routeEditor = RouteEditor(sdkContext)
val routeEditorSource = RouteEditorSource(sdkContext, routeEditor)
map.addSource(routeEditorSource)

routeEditor.setRouteParams(
    RouteParams(
        startPoint = RouteSearchPoint(
            coordinates = GeoPoint(latitude = 55.759909, longitude = 37.618806)
        ),
        finishPoint = RouteSearchPoint(
            coordinates = GeoPoint(latitude = 55.752425, longitude = 37.613983)
        )
    )
)

To build a route, you need to get points of the GeoPoint type, which are then used to create RouteSearchPoint. You can do it in multiple ways, two of them are described below.

The TouchEventsObserver interface contains onTap and onLongTouch methods that allow you to get a ScreenPoint. You can transfer an object of this class into GeoPoint using the screenToMap() method. As a result, you get coordinates of the map tap point.

    override fun onTap(point: ScreenPoint) {
        val geoPoint: GeoPoint? = map.camera.projection.screenToMap(point)
    }

You can get coordinates of an object (building, road) that is located at the tap point: use the getRenderedObjects() method. In this method, get an object of the DgisMapObject class with the id field. This ID is a stable numerical identifier of a directory object that allows you to send a search request and get information about an object, including geographic coordinates of its center.

map.getRenderedObjects(point).onResult {objects ->
    // Getting a DgisMapObject class object that is the closest to the tap
    val renderedObject = objects.firstOrNull { it.item.item is DgisMapObject } ?: return@onResult
    val mapObject = renderedObject.item.item as DgisMapObject

    // Creating a search request using the ID of this object
    searchManager
        .searchByDirectoryObjectId(mapObject.id)
        .onResult onDirectoryObjectReady@{ directoryObject ->
            // Getting an object and verifying it is not null
            directoryObject ?: return@onDirectoryObjectReady
            // Getting object coordinates as GeoPoint
            val geoPoint = directoryObject.markerPosition?.point ?: return@onDirectoryObjectReady
        }
}

Important

Coordinates of a center of a large object (for example, long and complicated ring roads) can be located far away from the camera viewport as the received object does not contain information on the camera location or the map tap spot. In such cases, use other methods to get coordinates.

For a route with intermediate points, a user is expected to visit each point in the defined order. If an intermediate point is missed, a route may be rebuilt:

  • If the GPS data shows that the user is moving not in the direction of the expected intermediate point, the route is rebuilt relatively to the current user location so that they visit the missed point. When the visit of the intermediate point is detected, the route continues.
  • If the moment of visiting the intermediate point is not detected due to a weak GPS signal but later the user location is detected on the route or next to it towards the next point, the previous intermediate point is considered visited and the route continues.