Маршруты | Mobile SDK | 2GIS Documentation
Android SDK
Личный кабинет

Маршруты

Чтобы проложить маршрут на карте, нужно создать два объекта: TrafficRouter для поиска оптимального маршрута и источник данных RouteMapObjectSource для отображения маршрута на карте.

Чтобы найти маршрут между двумя точками, нужно вызвать метод findRoute(), передав координаты точек в виде объектов RouteSearchPoint. Дополнительно можно указать параметры маршрута (RouteOptions), а также список промежуточных точек маршрута (список 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 routesFuture = trafficRouter.findRoute(startSearchPoint, finishSearchPoint)
val trafficRouter = TrafficRouter(sdkContext)

// После получения маршрута добавляем его на карту
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, но позже положение пользователя зафиксировано на маршруте по направлению к следующей точке или около него, точка считается пройденной и маршрут продолжается.