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

Маршруты

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

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

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

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

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

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)

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

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

// Ищем маршрут
val trafficRouter = TrafficRouter(sdkContext)
val routesFuture = trafficRouter.findRoute(startSearchPoint, finishSearchPoint)

// После получения маршрута добавляем его на карту
routesFuture.onResult { routes: List<TrafficRoute> ->
    var isActive = true
    var routeIndex = 0
    for (route in routes) {
        routeMapObjectSource.addObject(
            RouteMapObject(route, isActive, routeIndex)
        )
        isActive = false
        routeIndex++
    }
}

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

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

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

В интерфейсе TouchEventsObserver существуют методы onTap и onLongTouch, которые позволяют получить ScreenPoint. Объект этого класса можно преобразовать в GeoPoint с помощью метода screenToMap().

Таким образом, мы получим координаты в точке нажатия на карту.

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

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

map.getRenderedObjects(point).onResult {objects ->
    // Получим ближайший к месту нажатия объект класса DgisMapObject
    val renderedObject = objects.firstOrNull { it.item.item is DgisMapObject } ?: return@onResult
    val mapObject = renderedObject.item.item as DgisMapObject

    // Создадим поисковый запрос по идентификатору этого объекта
    searchManager
        .searchByDirectoryObjectId(mapObject.id)
        .onResult onDirectoryObjectReady@{ directoryObject ->
            // Получим объект и убедимся, что не null
            directoryObject ?: return@onDirectoryObjectReady
            // Получим координаты объекта в виде GeoPoint
            val geoPoint = directoryObject.markerPosition?.point ?: return@onDirectoryObjectReady
        }
}

Важно

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

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

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

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

  • avoidTollRoads: избегать ли платных дорог (по умолчанию false).
  • avoidUnpavedRoads: избегать ли грунтовых дорог (по умолчанию false).
  • avoidFerries: избегать ли паромных переправ (по умолчанию false).
  • avoidLockedRoads: избегать ли закрытых для проезда дорог (по умолчанию true).
  • routeSearchType: способ учёта данных о пробках при построении маршрута. Вы можете строить маршрут с учётом реальных (JAM) или статистических (STATIC) данных о пробках или построить кратчайший по расстоянию маршрут, даже если он не является оптимальным по времени (SHORTEST).
  • excludedAreas: список областей (не более 25), которые следует избегать при построении маршрута. Подробнее см. в разделе Исключение областей ниже.
val carOptions = CarRouteSearchOptions(
    avoidTollRoads = true,
    avoidUnpavedRoads = true,
    avoidFerries = true,
    avoidLockedRoads = true,
    routeSearchType = RouteSearchType.JAM,
    excludedAreas = listOf()
)

val routeSearchOptions = RouteSearchOptions(car = carOptions)

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

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

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

val taxiOptions = TaxiRouteSearchOptions(
    car = carOptions
)

val routeSearchOptions = RouteSearchOptions(taxi = taxiOptions)

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

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

  • car: базовые параметры поиска любых автомобильных маршрутов: см. параметры поиска маршрута для автомобилей.
  • truckLength: длина грузовика в миллиметрах.
  • truckHeight: высота грузовика в миллиметрах.
  • truckWidth: ширина грузовика в миллиметрах.
  • actualMass: фактическая масса грузовика в килограммах.
  • maxPermittedMass: разрешённая максимальная масса грузовика в килограммах.
  • axleLoad: нагрузка на ось в килограммах.
  • dangerousCargo: перевозится ли опасный груз (по умолчанию false).
  • explosiveCargo: перевозятся ли взрывчатые вещества в грузе (по умолчанию false).
  • passIds: список идентификаторов пропусков, которые разрешают движение грузового транспорта в пропускных зонах (TruckPassZonePassId).
  • fallbackOnCar: переключаться ли на поиск маршрута для легкового автомобиля, если по заданным параметрам невозможно найти грузовой маршрут (по умолчанию false).
val truckOptions = 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 = setOf(),
    fallbackOnCar = true
)

val routeSearchOptions = RouteSearchOptions(truck = truckOptions)

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

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

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

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

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

  • avoidCarRoads: избегать ли автомобильных дорог (по умолчанию false).
  • avoidStairways: избегать ли лестниц (по умолчанию false).
  • avoidUnderpassesAndOverpasses: избегать ли подземных и надземных переходов (по умолчанию false).
  • excludedAreas: список областей (не более 25), которые следует избегать при построении маршрута. Подробнее см. в разделе Исключение областей ниже.
val bicycleOptions = BicycleRouteSearchOptions(
    avoidCarRoads = true,
    avoidStairways = true,
    avoidUnderpassesAndOverpasses = true,
    excludedAreas = listOf()
)

val routeSearchOptions = RouteSearchOptions(bicycle = bicycleOptions)

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

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

  • avoidCarRoads: избегать ли автомобильных дорог (по умолчанию true).
  • avoidStairways: избегать ли лестниц (по умолчанию true).
  • avoidUnderpassesAndOverpasses: избегать ли подземных и надземных переходов (по умолчанию true).
  • excludedAreas: список областей (не более 25), которые следует избегать при построении маршрута. Подробнее см. в разделе Исключение областей ниже.
val scooterOptions = ScooterRouteSearchOptions(
    avoidCarRoads = true,
    avoidStairways = true,
    avoidUnderpassesAndOverpasses = true,
    excludedAreas = listOf()
)

val routeSearchOptions = RouteSearchOptions(scooter = scooterOptions)

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

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

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

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

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

  • avoidStairways: избегать ли лестниц (по умолчанию false).
  • avoidUnderpassesAndOverpasses: избегать ли подземных и надземных переходов (по умолчанию false).
  • useIndoor: строить ли маршруты внутри зданий (по умолчанию true).
  • excludedAreas: список областей (не более 25), которые следует избегать при построении маршрута. Подробнее см. в разделе Исключение областей ниже.
val pedestrianOptions = PedestrianRouteSearchOptions(
    avoidStairways = true,
    avoidUnderpassesAndOverpasses = true,
    useIndoor = false,
    excludedAreas = listOf()
)

val routeSearchOptions = RouteSearchOptions(pedestrian = pedestrianOptions)

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

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

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

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

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

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

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