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

Маршруты

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

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

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

let trafficRouter = TrafficRouter(context: sdk.context)
let routesFuture = trafficRouter.findRoute(
	startPoint: startPoint,
	finishPoint: finishPoint,
	routeSearchOptions: routeSearchOptions
)

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

// Создаём источник данных.
let routeMapObjectSource = RouteMapObjectSource(context: sdk.context, routeVisualizationType: .normal)
map.addSource(source: routeMapObjectSource)

// Ищем маршрут.
self.routeSearchCancellable = routesFuture.sink { routes in
	// Ддобавляем их на карту.
	for (index, route) in routes.enumerated() {
		let routeMapObject = RouteMapObject(
			route: route,
			isActive: index == 0,
			index: RouteIndex(value: UInt64(index)),
			displayFlags: nil
		)
		routeMapObjectSource.addObject(item: routeMapObject)
	}
} failure: { error in
	print("Не удалось найти маршрут: \(error)")
}

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

Для получения географических координат места нажатия нужно получить ScreenPoint, как примере Получениеобъектовпоэкраннымкоординатам

func tap(location: CGPoint) {
	let scale = UIScreen.main.nativeScale
	let point = ScreenPoint(x: Float(location.x * scale), y: Float(location.y * scale))
	...

ScreenPoint можно преобразовать в географические координаты с помощью метода screenToMap()

func tap(location: CGPoint) {
	let scale = UIScreen.main.nativeScale
	let point = ScreenPoint(x: Float(location.x * scale), y: Float(location.y * scale))
	let geoPoint = map.camera.projection.screenToMap(point: point)
	...

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

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

private func tap(point: ScreenPoint, tapRadius: ScreenDistance) {
	let scale = UIScreen.main.nativeScale
	let point = ScreenPoint(x: Float(location.x * scale), y: Float(location.y * scale))
	self.getRenderedObjectsCancellable?.cancel()
	let cancel = self.map.getRenderedObjects(centerPoint: point).sink(
		receiveValue: {
			infos in
			// Получим ближайший к месту нажатия объект класса DgisMapObject
				guard let info = infos.first(
					where: {
						$0.item.item is DgisMapObject
					}
				) else { return }
				let mapObject = info.item.item as! DgisMapObject

				// Создадим поисковый запрос по идентификатору этого объекта
				self.searchCancellable?.cancel()
				self.searchCancellable = self.searchManager.searchByDirectoryObjectId(
					objectId: mapObject.id
				)
				// Получим объект из поискового запроса
				.sinkOnMainThread(receiveValue: { [weak self] object in
					self?.directoryObject = object
					// Получим координаты объекта в виде GeoPoint
					let geoPoint = self?.directoryObject?.markerPosition?.point
				},
					failure: { .. }
				)

		},
		failure: { ... }
	)
	...
}

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