Перейти к основному содержимому

Маршруты

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

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

Построение маршрута

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

  • 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ГИС. Если за определённое время не удаётся построить маршрут на онлайн-данных, используются предварительно загруженные данные, если они есть.

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