Routing | Mobile SDK | 2GIS Documentation
Android SDK

Routing

This chapter describes how to build a route for different types of transport and display it on the map. To build any type of route, you need to define the following components:

  • Route points: the starting one, the finishing one, and (if needed) intermediate ones. Ways of getting point coordinates are described below.
  • Route search parameters. A set of parameters depends on the transport type that the route is built for.

To create a route on the map, you need to create two objects:

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 trafficRouter = TrafficRouter(sdkContext)
val routesFuture = trafficRouter.findRoute(startSearchPoint, finishSearchPoint)

// 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.

To build a route for a car, specify the car property in RouteSearchOptions. Additionally, you can configure route search parameters CarRouteSearchOptions:

  • avoidTollRoads: whether to avoid toll roads (false by default).
  • avoidUnpavedRoads: whether to avoid unpaved roads (false by default).
  • avoidFerries: whether to avoid ferry crossings (false by default).
  • avoidLockedRoads: whether to avoid roads that are closed for passage (true by default).
  • routeSearchType: a way of considering traffic jam data when building a route. You can build a route based on real-time (jam) or statistical (statistic) traffic jam data or you can build the shortest route in distance even if it is not optimal in time (shortest).
  • excludedAreas: a list of areas (not more than 25) to avoid when building a route. For details, see the Excluding areas section below.
val carOptions = CarRouteSearchOptions(
    avoidTollRoads = true,
    avoidUnpavedRoads = true,
    avoidFerries = true,
    avoidLockedRoads = true,
    routeSearchType = RouteSearchType.JAM,
    excludedAreas = listOf()
)

val routeSearchOptions = RouteSearchOptions(car = carOptions)

Pass the created routeSearchOptions to the findRoute() function call when building a route.

To build a route for a taxi, specify the taxi property in RouteSearchOptions.

Additionally, you can configure route search parameters TaxiRouteSearchOptions. To build a taxi route, you need to define search parameters for common car routes first and then reuse them in the car parameter:

val taxiOptions = TaxiRouteSearchOptions(
    car = carOptions
)

val routeSearchOptions = RouteSearchOptions(taxi = taxiOptions)

Pass the created routeSearchOptions to the findRoute() function call when building a route.

To build a route for a truck, specify the truck property in RouteSearchOptions. Additionally, you can configure route search parameters TruckRouteSearchOptions:

  • car: common parameters for any car routes: see search parameters for car routes.
  • truckLength: truck length in millimeters.
  • truckHeight: truck height in millimeters.
  • truckWidth: truck width in millimeters.
  • actualMass: actual mass of the truck in kilograms.
  • maxPermittedMass: maximum permitted of a truck in kilograms.
  • axleLoad: axle load in kilograms.
  • dangerousCargo: whether dangerous cargo is transported (false by default).
  • explosiveCargo: whether explosive cargo is transported (false by default).
  • passIds: a list of IDs of the passes that allow the truck to drive through pass zones (TruckPassZonePassId).
  • fallbackOnCar: whether to switch to car routing if a truck route with specified parameters cannot be built (false by default).
val truckOptions = TruckRouteSearchOptions(
    car = carOptions,
    truckLength = 12000,                 // 12 meters
    truckHeight = 4200,                  // 4.2 meters
    truckWidth = 2500,                   // 2.5 meters
    actualMass = 18000,                  // 18 tons
    maxPermittedMass = 20000,            // 20 tons
    axleLoad = 8000,                     // 8 tons
    dangerousCargo = true,
    explosiveCargo = false,
    passIds = setOf(),
    fallbackOnCar = true
)

val routeSearchOptions = RouteSearchOptions(truck = truckOptions)

Pass the created routeSearchOptions to the findRoute() function call when building a route.

To build a route for a public transport, specify the publicTransport property in RouteSearchOptions. Additionally, you can configure route search parameters PublicTransportRouteSearchOptions:

  • startTime: route start time in UTC. If not specified, the current time is used.
  • useSchedule: whether to consider the public transport schedule.
  • transportTypes: a list of public transport types that can be used for completing the route. If the list is empty, a route is built for all supported transport types. See the full list of types in PublicTransportTypeOptionSet.
val publicTransportOptions = PublicTransportRouteSearchOptions(
    startTime = TimePoint.now(),
    useSchedule = true,
    transportTypes = EnumSet.of(
        PublicTransportType.BUS,
        PublicTransportType.TROLLEYBUS,
        PublicTransportType.TRAM,
        PublicTransportType.METRO,
        PublicTransportType.SUBURBAN_TRAIN
    )
)

val routeSearchOptions = RouteSearchOptions(publicTransport = publicTransportOptions)

Pass the created routeSearchOptions to the findRoute() function call when building a route.

To build a route for a bicycle, specify the bicycle property in RouteSearchOptions. Additionally, you can configure route search parameters BicycleRouteSearchOptions:

  • avoidCarRoads: whether to avoid car roads (false by default).
  • avoidStairways: whether to avoid stairways (false by default).
  • avoidUnderpassesAndOverpasses: whether to avoid underpasses and overpasses (false by default).
  • excludedAreas: a list of areas (not more than 25) to avoid when building a route. For details, see the Excluding areas section below.
val bicycleOptions = BicycleRouteSearchOptions(
    avoidCarRoads = true,
    avoidStairways = true,
    avoidUnderpassesAndOverpasses = true,
    excludedAreas = listOf()
)

val routeSearchOptions = RouteSearchOptions(bicycle = bicycleOptions)

Pass the created routeSearchOptions to the findRoute() function call when building a route.

To build a route for a scooter, specify the scooter property in RouteSearchOptions. Additionally, you can configure route search parameters ScooterRouteSearchOptions:

  • avoidCarRoads: whether to avoid car roads (true by default).
  • avoidStairways: whether to avoid stairways (true by default).
  • avoidUnderpassesAndOverpasses: whether to avoid underpasses and overpasses (true by default).
  • excludedAreas: a list of areas (not more than 25) to avoid when building a route. For details, see the Excluding areas section below.
val scooterOptions = ScooterRouteSearchOptions(
    avoidCarRoads = true,
    avoidStairways = true,
    avoidUnderpassesAndOverpasses = true,
    excludedAreas = listOf()
)

val routeSearchOptions = RouteSearchOptions(scooter = scooterOptions)

Pass the created routeSearchOptions to the findRoute() function call when building a route.

Pedestrian routes can include moving inside a building (for example, you can build a route to a specific shop in a shopping mall). If some route point is located indoors, you must specify additional parameters for it: objectId (ID of the object to build a route to) and levelId (ID of the building floor where the object is located).

val indoorPoint = RouteSearchPoint(
    coordinates = GeoPoint(latitude = 55.752425, longitude = 37.613983),
    objectId = DgisObjectId(objectId = 67890, entranceId = 2),
    levelId = LevelId(value = 3)
)

For more information about indoor navigation, see the Navigation chapter.

To build a pedestrian route, specify the pedestrian property in RouteSearchOptions. Additionally, you can configure route search parameters PedestrianRouteSearchOptions:

  • avoidStairways: whether to avoid stairways (false by default).
  • avoidUnderpassesAndOverpasses: whether to avoid underpasses and overpasses (false by default).
  • useIndoor: whether to build indoor routes (true by default).
  • excludedAreas: a list of areas (not more than 25) to avoid when building a route. For details, see the Excluding areas section below.
val pedestrianOptions = PedestrianRouteSearchOptions(
    avoidStairways = true,
    avoidUnderpassesAndOverpasses = true,
    useIndoor = false,
    excludedAreas = listOf()
)

val routeSearchOptions = RouteSearchOptions(pedestrian = pedestrianOptions)

Pass the created routeSearchOptions to the findRoute() function call when building a route.

To exclude a specific area when building a route, create an ExcludedArea object with the following parameters:

  • type: geometry of the excluded area. See the list of available values in ExcludedAreaType.
  • severity: priority of excluding the area (how critical it is to avoid the area). See the list of available values in ExcludedAreaSeverity.
  • extent: size of the excluded area (not more than 25 km).
  • points: coordinates of excluded area points of the GeoPoint type (not more than 500).

Example of an excluded polygon:

// Polygon vertices
val points = listOf(
    GeoPoint(latitude = 55.759909, longitude = 37.618806),
    GeoPoint(latitude = 55.752425, longitude = 37.613983),
    GeoPoint(latitude = 55.753567, longitude = 37.622995),
    GeoPoint(latitude = 55.760523, longitude = 37.625613)
)

val polygonExcludedArea = ExcludedArea(
    type = ExcludedAreaType.POLYGON,
    severity = ExcludedAreaSeverity.HARD,
    extent = RouteDistance(500.0),
    points = points
)

By default, routing works in hybrid mode: using data from Urbi servers is prioritized. If a route cannot be built from online data after a defined timeout, preloaded data is used.

To load data for offline usage, you must get respective rights for your access key and download required territories. See preparation steps for working with offline data.