Routing | Mobile SDK | 2GIS Documentation
Flutter 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 build a route on the map, you need to create two objects:

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

import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

final routeSearchOptions = sdk.RouteSearchOptions.car(sdk.CarRouteSearchOptions());
final startPoint = sdk.RouteSearchPoint(coordinates: GeoPoint(latitude: 55.759909, longitude: 37.618806));
final finishPoint = sdk.RouteSearchPoint(coordinates: GeoPoint(latitude: 55.752425, longitude: 37.613983));

final trafficRouter = sdk.TrafficRouter(sdkContext);
final routesFuture = trafficRouter.findRoute(startPoint, finishPoint, routeSearchOptions);

The call returns 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.

import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

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

// Find a route
final trafficRouter = sdk.TrafficRouter(sdkContext);
final List<sdk.TrafficRoute> routes = await trafficRouter.findRoute(startSearchPoint, finishSearchPoint).value;

// After receiving the route, add it to the map
int routeIdx = 0;
bool isActive = true;
routes.forEach((sdk.TrafficRoute route) {
  routeMapObjectSource.addObject(sdk.RouteMapObject(route, isActive, routeIdx));
  routeIdx += 1;
  isActive = false;
})

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

final routeEditor = sdk.RouteEditor(sdkContext);
final routeEditorSource = sdk.RouteEditorSource(sdkContext, routeEditor);
map.addSource(routeEditorSource);

routeEditor.setRouteParams(
  sdk.RouteEditorRouteParams(
    startPoint: startPoint,
    finishPoint: finishPoint,
    routeSearchOptions: routeSearchOptions,
  ),
);

To build a route, you need to get GeoPoint points, which are used to create a RouteSearchPoint object. One of the ways to do this is described below.

You can get the coordinates of the object (e.g., building, road) at the place where the user taps on the map. Use the getRenderedObjects() method to get a DgisMapObject object with an id field. This identifier is a stable numeric identifier of the object directory that can help you perform a search query and get information about the object, including the geographical coordinates of its center.

import 'package:dgis_mobile_sdk_map/dgis.dart' as sdk;

map.getRenderedObjects(sdk.ScreenPoint()).then((List<sdk.RenderedObjectInfo> info) {
  // Get the closest object to the tap spot inside the specified radius
  final sdk.RenderedObject obj = info.first.item;

  // In this example, we want to search for information about the selected object in the directory.
  // To do this, make sure that the type of this object can be found
  if (obj.source is sdk.DgisSource && obj.item is sdk.DgisMapObject) {
    final source = obj.source as sdk.DgisSource;

    // Search
    final foundObject =
        await sdk.SearchManager.createOnlineManager(sdkContext)
            .searchByDirectoryObjectId((obj.item as sdk.DgisMapObject).id)
            .value;

    final sdk.GeoPoint? geoPoint = foundObject.markerPosition?.point;
  }
});

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.
import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

final carOptions = sdk.CarRouteSearchOptions(
    avoidTollRoads: true,
    avoidUnpavedRoads: true,
    avoidFerries: true,
    avoidLockedRoads: true,
    routeSearchType: sdk.RouteSearchType.jam,
    excludedAreas: []
  );

final routeSearchOptions = sdk.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:

import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

final taxiOptions = sdk.TaxiRouteSearchOptions(
    car: carOptions
  );

final routeSearchOptions = sdk.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).
import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

final truckOptions = sdk.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: <sdk.TruckPassZonePassId>{},
    fallbackOnCar: true
  );

final routeSearchOptions = sdk.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.
import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

final publicTransportOptions = sdk.PublicTransportRouteSearchOptions(
  startTime: DateTime.now().toUtc(),
  useSchedule: true,
  transportTypes: sdk.PublicTransportTypeEnumSet({
    sdk.PublicTransportType.bus,
    sdk.PublicTransportType.trolleybus,
    sdk.PublicTransportType.tram,
    sdk.PublicTransportType.metro,
    sdk.PublicTransportType.suburbanTrain,
  });
);

final routeSearchOptions = sdk.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.
import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

final bicycleOptions = sdk.BicycleRouteSearchOptions(
  avoidCarRoads: true,
  avoidStairways: true,
  avoidUnderpassesAndOverpasses: true,
  excludedAreas: []
);

final routeSearchOptions = sdk.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.
import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

final scooterOptions = sdk.ScooterRouteSearchOptions(
  avoidCarRoads: true,
  avoidStairways: true,
  avoidUnderpassesAndOverpasses: true,
  excludedAreas: []
);

final routeSearchOptions = sdk.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).

import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

final finishPoint = sdk.RouteSearchPoint(
  coordinates: GeoPoint(latitude: 55.752425, longitude: 37.613983),
  objectId: sdk.DgisObjectId(
      objectId: 67890,
      entranceId: 2
  ),
  levelId: sdk.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.
import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

final pedestrianOptions = sdk.PedestrianRouteSearchOptions(
  avoidStairways: false,
  avoidUnderpassesAndOverpasses: false,
  useIndoor: false,
  excludedAreas: []
);

final routeSearchOptions = sdk.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:

import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

// Polygon vertices
final points = [
  sdk.GeoPoint(latitude: 55.759909, longitude: 37.618806),
  sdk.GeoPoint(latitude: 55.752425, longitude: 37.613983),
  sdk.GeoPoint(latitude: 55.753567, longitude: 37.622995),
  sdk.GeoPoint(latitude: 55.760523, longitude: 37.625613)
];

final polygonExcludedArea = sdk.ExcludedArea(
  type: sdk.ExcludedAreaType.polygon,
  severity: sdk.ExcludedAreaSeverity.hard,
  extent: sdk.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.