Маршруты | Mobile SDK | 2GIS Documentation
Flutter SDK

Маршруты

В этом разделе описывается построение маршрутов для разных видов транспорта и отображение их на карте. Для построения любого маршрута вам понадобятся следующие компоненты:

  • Точки маршрута: начальная, конечная и, если необходимо, промежуточные. Способы получения координат точек описаны ниже.
  • Параметры поиска маршрута. Набор параметров зависит от типа транспорта, для которого строится маршрут.

Чтобы проложить маршрут на карте, создайте два объекта:

  • TrafficRouter для поиска оптимального маршрута;
  • Источник данных RouteMapObjectSource для отображения маршрута на карте.

Чтобы найти маршрут между двумя точками, вызовите метод findRoute(), передав координаты точек в виде объектов RouteSearchPoint. Дополнительно можно указать параметры маршрута (RouteSearchOptions), а также список промежуточных точек маршрута (список RouteSearchPoint).

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);

Вызов findRoute() вернёт отложенный результат со списком объектов TrafficRoute. Чтобы отобразить найденный маршрут на карте, нужно на основе этих объектов создать объекты RouteMapObject и добавить их в источник данных RouteMapObjectSource.

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

// Создаём источник данных
final sdk.RouteMapObjectSource routeMapObjectSource = sdk.RouteMapObjectSource(sdkContext, RouteVisualizationType.NORMAL)
map.addSource(routeMapObjectSource)

// Ищем маршрут
final trafficRouter = sdk.TrafficRouter(sdkContext);
final List<sdk.TrafficRoute> routes = await trafficRouter.findRoute(startSearchPoint, finishSearchPoint).value;

// После получения маршрута добавляем его на карту
int routeIdx = 0;
bool isActive = true;
routes.forEach((sdk.TrafficRoute route) {
  routeMapObjectSource.addObject(sdk.RouteMapObject(route, isActive, routeIdx));
  routeIdx += 1;
  isActive = false;
})

Вместо пары TrafficRouter и RouteMapObjectSource для построения маршрута можно использовать RouteEditor и RouteEditorSource. В таком случае не нужно обрабатывать список TrafficRoute, достаточно передать координаты маршрута в виде объекта RouteEditorRouteParams в метод setRouteParams(), и маршрут отобразится автоматически.

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

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

Для построения маршрута необходимо получить точки типа GeoPoint, которые далее используются для создания RouteSearchPoint. Существует множество способов это сделать, ниже описан один из них.

Можно получить координаты объекта (здания, дороги), который находится в месте клика. Для этого понадобится метод getRenderedObjects(). В нем нужно получить объект класса DgisMapObject, который имеет поле id. Этот идентификатор является стабильным числовым идентификатором объекта справочника, с помощью которого можно выполнить поисковый запрос и получить информацию об объекте, в том числе географические координаты его центра.

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

map.getRenderedObjects(sdk.ScreenPoint()).then((List<sdk.RenderedObjectInfo> info) {
  // Получим ближайший к месту нажатия объект внутри установленного радиуса
  final sdk.RenderedObject obj = info.first.item;

  // В этом примере мы хотим найти информацию о выбранном объекте в справочнике.
  // Для этого мы должны убедиться, что тип этого объекта может быть найден
  if (obj.source is sdk.DgisSource && obj.item is sdk.DgisMapObject) {
    final source = obj.source as sdk.DgisSource;

    // Произведем поиск
    final foundObject =
        await sdk.SearchManager.createOnlineManager(sdkContext)
            .searchByDirectoryObjectId((obj.item as sdk.DgisMapObject).id)
            .value;

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

Важно

Координаты центра для больших объектов (например, МКАД) могут находиться далеко за пределами области видимости камеры, так как полученный объект не учитывает расположение камеры или места нажатия на карту. В случае с такими объектами лучше использовать другие способы получения координат.

Для маршрута с промежуточными точками предполагается, что пользователь посетит каждую из этих точек на маршруте по очереди. Если промежуточная точка пропущена, маршрут может перестроиться:

  • Если по данным GPS видно, что пользователь движется не в сторону нужной промежуточной точки, маршрут перестраивается относительно текущего положения пользователя так, чтобы он посетил пропущенную точку. Когда посещение точки будет зафиксировано, маршрут продолжится.
  • Если момент посещения промежуточной точки не зафиксирован из-за слабого сигнала GPS, но позже положение пользователя зафиксировано на маршруте по направлению к следующей точке или около него, точка считается пройденной и маршрут продолжается.

Чтобы построить маршрут для легкового автомобиля, укажите свойство car в RouteSearchOptions. Дополнительно вы можете настроить параметры построения маршрута CarRouteSearchOptions:

  • avoidTollRoads: избегать ли платных дорог (по умолчанию false).
  • avoidUnpavedRoads: избегать ли грунтовых дорог (по умолчанию false).
  • avoidFerries: избегать ли паромных переправ (по умолчанию false).
  • avoidLockedRoads: избегать ли закрытых для проезда дорог (по умолчанию true).
  • routeSearchType: способ учёта данных о пробках при построении маршрута. Вы можете строить маршрут с учётом реальных (jam) или статистических (statistic) данных о пробках или построить кратчайший по расстоянию маршрут, даже если он не является оптимальным по времени (shortest).
  • excludedAreas: список областей (не более 25), которые следует избегать при построении маршрута. Подробнее см. в разделе Исключение областей ниже.
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);

Передайте готовые параметры routeSearchOptions в вызов функции findRoute() при построении маршрута.

Чтобы построить маршрут для такси, укажите свойство taxi в RouteSearchOptions.

Дополнительно вы можете настроить параметры построения маршрута TaxiRouteSearchOptions. Для поиска маршрута для такси нужно сначала задать параметры поиска обычных автомобильных маршрутов, а затем переиспользовать их в параметре car:

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

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

final routeSearchOptions = sdk.RouteSearchOptions.taxi(taxiOptions);

Передайте готовые параметры routeSearchOptions в вызов функции findRoute() при построении маршрута.

Чтобы построить маршрут для грузового автомобиля, укажите свойство truck в RouteSearchOptions. Дополнительно вы можете настроить параметры построения маршрута TruckRouteSearchOptions:

  • car: базовые параметры поиска любых автомобильных маршрутов: см. параметры поиска маршрута для автомобилей.
  • truckLength: длина грузовика в миллиметрах.
  • truckHeight: высота грузовика в миллиметрах.
  • truckWidth: ширина грузовика в миллиметрах.
  • actualMass: фактическая масса грузовика в килограммах.
  • maxPermittedMass: разрешённая максимальная масса грузовика в килограммах.
  • axleLoad: нагрузка на ось в килограммах.
  • dangerousCargo: перевозится ли опасный груз (по умолчанию false).
  • explosiveCargo: перевозятся ли взрывчатые вещества в грузе (по умолчанию false).
  • passIds: список идентификаторов пропусков, которые разрешают движение грузового транспорта в пропускных зонах (TruckPassZonePassId).
  • fallbackOnCar: переключаться ли на поиск маршрута для легкового автомобиля, если по заданным параметрам невозможно найти грузовой маршрут (по умолчанию false).
import 'package:dgis_mobile_sdk_full/dgis.dart' as sdk;

final truckOptions = sdk.TruckRouteSearchOptions(
    car: carOptions,
    truckLength: 12000,                 // 12 метров
    truckHeight: 4200,                  // 4,2 метра
    truckWidth: 2500,                   // 2,5 метра
    actualMass: 18000,                  // 18 тонн
    maxPermittedMass: 20000,            // 20 тонн
    axleLoad: 8000,                     // 8 тонн
    dangerousCargo: true,
    explosiveCargo: false,
    passIds: <sdk.TruckPassZonePassId>{},
    fallbackOnCar: true
  );

final routeSearchOptions = sdk.RouteSearchOptions.truck(truckOptions);

Передайте готовые параметры routeSearchOptions в вызов функции findRoute() при построении маршрута.

Чтобы построить маршрут для проезда на общественном транспорте, укажите свойство publicTransport в RouteSearchOptions. Дополнительно вы можете настроить параметры построения маршрута PublicTransportRouteSearchOptions:

  • startTime: время старта маршрута в UTC. Если не указано, используется текущее время.
  • useSchedule: учитывать ли расписание движения общественного транспорта.
  • transportTypes: список типов общественного транспорта, которые могут быть использованы для проезда по маршруту. Если список пустой, маршрут будет строиться для всех поддерживаемых типов транспорта. Полный список типов см. в PublicTransportType.
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);

Передайте готовые параметры routeSearchOptions в вызов функции findRoute() при построении маршрута.

Чтобы построить маршрут для велосипеда, укажите свойство bicycle в RouteSearchOptions. Дополнительно вы можете настроить параметры построения маршрута BicycleRouteSearchOptions:

  • avoidCarRoads: избегать ли автомобильных дорог (по умолчанию false).
  • avoidStairways: избегать ли лестниц (по умолчанию false).
  • avoidUnderpassesAndOverpasses: избегать ли подземных и надземных переходов (по умолчанию false).
  • excludedAreas: список областей (не более 25), которые следует избегать при построении маршрута. Подробнее см. в разделе Исключение областей ниже.
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);

Передайте готовые параметры routeSearchOptions в вызов функции findRoute() при построении маршрута.

Чтобы построить маршрут для самоката, укажите свойство scooter в RouteSearchOptions. Дополнительно вы можете настроить параметры построения маршрута ScooterRouteSearchOptions:

  • avoidCarRoads: избегать ли автомобильных дорог (по умолчанию true).
  • avoidStairways: избегать ли лестниц (по умолчанию true).
  • avoidUnderpassesAndOverpasses: избегать ли подземных и надземных переходов (по умолчанию true).
  • excludedAreas: список областей (не более 25), которые следует избегать при построении маршрута. Подробнее см. в разделе Исключение областей ниже.
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);

Передайте готовые параметры routeSearchOptions в вызов функции findRoute() при построении маршрута.

Пешеходные маршруты могут включать в себя перемещения внутри зданий (например, вы можете построить маршрут до определённого магазина в торговом центре). Если одна из точек маршрута находится внутри здания, для неё необходимо указать дополнительные параметры objectId (идентификатор объекта, к которому нужно проложить маршрут) и levelId (идентификатор этажа здания, на котором находится объект).

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));

Подробнее о ведении по маршруту внутри зданий см. в разделе Навигация.

Чтобы построить пешеходный маршрут, укажите свойство pedestrian в RouteSearchOptions. Дополнительно вы можете настроить параметры построения маршрута PedestrianRouteSearchOptions:

  • avoidStairways: избегать ли лестниц (по умолчанию false).
  • avoidUnderpassesAndOverpasses: избегать ли подземных и надземных переходов (по умолчанию false).
  • useIndoor: строить ли маршруты внутри зданий (по умолчанию true).
  • excludedAreas: список областей (не более 25), которые следует избегать при построении маршрута. Подробнее см. в разделе Исключение областей ниже.
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);

Передайте готовые параметры routeSearchOptions в вызов функции findRoute() при построении маршрута.

Чтобы исключить определённую область при построении маршрута, создайте объект ExcludedArea со следующими параметрами:

  • type: геометрическая форма исключаемой области. Список возможных значений см. в ExcludedAreaType.
  • severity: приоритет исключения области (насколько важно её избегать). Список возможных значений см. в ExcludedAreaSeverity.
  • extent: размер исключаемой области (не более 25 км).
  • points: координаты точек исключаемой области типа GeoPoint (не более 500).

Пример исключаемой области в форме многоугольника:

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

// Вершины многоугольника
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
);

По умолчанию построение маршрута работает в гибридном режиме: в первую очередь используются данные с серверов 2ГИС. Если за определённое время не удаётся построить маршрут на онлайн-данных, используются предварительно загруженные данные, если они есть.

Чтобы загрузить данные для работы офлайн, необходимо получить соответствующие права в ключе доступа и скачать необходимые территории. См. подготовительные шаги к работе с офлайн-данными.