Draw a route line with the alternative route on NavigationMapView

Draw multiple route lines on NavigationMapView, with one of them designated as an alternative route.

This example shows how to draw multiple route lines with one selected as an alternative route on NavigationMapView

  • We first request a route with NavigationRouteOptions and enable includesAlternativeRoutes as true, this allows the backend to calculate and provide multiple route lines

  • Then we can set one of the routes as an alternative route and show all the route info on NavigationMapView

docs-image

For all code examples, refer to Navigation Code Examples

DrawAlternativeRouteController view source

1
import UIKit
2
import NbmapNavigation
3
import NbmapCoreNavigation
4
import NbmapDirections
5
import Nbmap
6
7
class DrawAlternativeRouteController: UIViewController, NGLMapViewDelegate {
8
9
var navigationMapView: NavigationMapView? {
10
didSet {
11
oldValue?.removeFromSuperview()
12
if let navigationMapView = navigationMapView {
13
view.insertSubview(navigationMapView, at: 0)
14
}
15
}
16
}
17
18
var routes : [Route]? {
19
didSet {
20
guard let routes = routes,
21
let current = routes.first else { navigationMapView?.removeRoutes(); return }
22
23
navigationMapView?.showRoutes(routes)
24
navigationMapView?.showWaypoints(current)
25
navigationMapView?.showRouteDurationSymbol(routes)
26
}
27
}
28
29
override func viewDidLoad() {
30
super.viewDidLoad()
31
32
let origin = CLLocation(latitude: 37.77440680146262, longitude: -122.43539772352648)
33
let destination = CLLocation(latitude: 37.779664450073, longitude: -122.43245802247301)
34
35
self.navigationMapView = NavigationMapView(frame: view.bounds)
36
navigationMapView?.userTrackingMode = .followWithHeading
37
navigationMapView?.delegate = self
38
navigationMapView?.navigationMapDelegate = self
39
40
self.view.setNeedsLayout()
41
42
requestRoutes(origin: origin, destination: destination)
43
}
44
45
func requestRoutes(origin: CLLocation, destination: CLLocation){
46
47
let options = NavigationRouteOptions(origin: origin, destination: destination)
48
/**
49
Sets whether the route contains an alternate route
50
By default , it set to `false`
51
*/
52
options.includesAlternativeRoutes = true
53
54
/**
55
The route classes that the calculated routes will avoid.
56
We can set an array road class to avoid. This property can be set to `.toll`,`.ferry`,`.highway`
57
By default , this property is set to empty
58
*/
59
options.roadClassesToAvoid = [.toll,.ferry,.highway]
60
/**
61
Set up the navigation measurement unit
62
This property should be set to `.metric` or `.imperial`
63
By default , this property is set to the unit follow with current system locale.
64
*/
65
options.distanceMeasurementSystem = .imperial
66
67
/**
68
Set specifying the primary mode of transportation for the routes.
69
This property should be set to `NBNavigationModeCar`, `NBNavigationModeAuto`, `NBNavigationModeBike`, `NBNavigationMode4W`,`NBNavigationMode2W`,`NBNavigationMode6W`, or `NBNavigationModeEscooter`. The default value of this property is `NBNavigationMode4W`, which specifies driving directions.
70
*/
71
options.profileIdentifier = NBNavigationMode.mode4W
72
/**
73
Set the departureTime of the route , By default , it sets the current timestamp since from 1970
74
*/
75
options.departureTime = Int(Date().timeIntervalSince1970)
76
77
/**
78
Set up the locale in which the route's instructions are written.
79
If you use NbmapDirections.swift with the Nbmap Directions API, this property affects the sentence contained within the `RouteStep.instructions` property, but it does not affect any road names contained in that property or other properties such as `RouteStep.name`.
80
The Navigation API can provide instructions in [a number of languages]. Set this property to `Bundle.main.preferredLocalizations.first` or `Locale.autoupdatingCurrent` to match the application's language or the system language, respectively.
81
By default, this property is set to the current system locale.
82
*/
83
options.locale = Locale.autoupdatingCurrent
84
85
/**
86
Set map options, This property may make the ETA more accurate. If set to `NBMapOption.valhala`, shapeFormat needs to be set to `polyline`.
87
By default , the value of this property is `NBMapOption.none`
88
*/
89
options.mapOption = NBMapOption.none
90
/**
91
Format of the data from which the shapes of the returned route and its steps are derived.
92
93
This property has no effect on the returned shape objects, although the choice of format can significantly affect the size of the underlying HTTP response.
94
95
The default value of this property is `polyline6`.
96
*/
97
options.shapeFormat = .polyline6
98
99
Directions.shared.calculate(options) { [weak self] routes, error in
100
guard let weakSelf = self else {
101
return
102
}
103
guard error == nil else {
104
print(error!)
105
return
106
}
107
108
guard let routes = routes else { return }
109
110
111
// Process or display routes information.For example, display the routes, waypoints and duration symbol on the map
112
weakSelf.navigationMapView?.showRoutes(routes)
113
weakSelf.navigationMapView?.showRouteDurationSymbol(routes)
114
115
guard let current = routes.first else { return }
116
weakSelf.navigationMapView?.showWaypoints(current)
117
weakSelf.routes = routes
118
}
119
}
120
}
121
122
extension DrawAlternativeRouteController: NavigationMapViewDelegate {
123
// Delegate method called when the user selects a route
124
func navigationMapView(_ mapView: NavigationMapView, didSelect route: Route) {
125
guard let routes = routes else { return }
126
guard let index = routes.firstIndex(where: { $0 == route }) else { return }
127
self.routes!.remove(at: index)
128
self.routes!.insert(route, at: 0)
129
}
130
}

The code first creates a NavigationRouteOptions object. This object specifies the parameters for the route calculation. In this case, the options specify that the route should include an alternate route, that it should avoid toll roads, ferries, and highways, and that it should be calculated in imperial units. The code then calls the calculate() method on the Directions object. This method calculates the routes and returns them in an array. The code then loops through the array and displays the routes on the map. The code also defines a delegate method called navigationMapView(_:didSelect:). This method is called when the user selects a route. The method removes the selected route from the array and inserts it at the beginning of the array. This ensures that the selected route is always displayed at the top of the map. Here is a more detailed explanation of each step in the code:

  • Create a NavigationRouteOptions object.

    1
    let options = NavigationRouteOptions(origin: origin, destination: destination)

    This code creates a NavigationRouteOptions object. The origin property specifies the starting location of the route, and the destination property specifies the ending location of the route.

  • Set the options for the route calculation.

    1
    options.includesAlternativeRoutes = true
    2
    options.roadClassesToAvoid = [.toll, .ferry, .highway]
    3
    options.distanceMeasurementSystem = .imperial
    4
    options.profileIdentifier = NBNavigationMode.mode4W
    5
    options.departureTime = Int(Date().timeIntervalSince1970)
    6
    options.locale = Locale.autoupdatingCurrent
    7
    options.mapOption = NBMapOption.none
    8
    options.shapeFormat = .polyline6

    This code sets the options for the route calculation. The includesAlternativeRoutes property specifies that the route calculation should include an alternate route. The roadClassesToAvoid property specifies that the route should avoid toll roads, ferries, and highways. The distanceMeasurementSystem property specifies that the distance should be measured in imperial units. The profileIdentifier property specifies that the route should be calculated for a car. The departureTime property specifies the time at which the route should start. The locale property specifies the locale in which the route instructions should be written. The mapOption property specifies that the route should be calculated using Valhalla. The shapeFormat property specifies that the route should be returned as a polyline.

  • Calculate the routes.

    1
    Directions.shared.calculate(options) { [weak self] routes, error in
    2
    guard let weakSelf = self else {
    3
    return
    4
    }
    5
    guard error == nil else {
    6
    print(error!)
    7
    return
    8
    }
    9
    10
    guard let routes = routes else { return }

    This code calls the calculate() method on the Directions object. The calculate() method calculates the routes and returns them in an array. The code then checks to make sure that the calculation was successful. If the calculation was successful, the code stores the routes in a variable.

  • Display the routes on the map.

    1
    weakSelf.navigationMapView?.showRoutes(routes)
    2
    weakSelf.navigationMapView?.showRouteDurationSymbol(routes)
    3
    4
    guard let current = routes.first else { return }
    5
    weakSelf.navigationMapView?.showWaypoints(current)
    6
    weakSelf.routes = routes
    7
    }

    This code displays the routes on the map. The showRoutes() method displays the routes as lines on the map. The showRouteDurationSymbol() method displays a symbol on the map that shows the duration of each route. The showWaypoints() method displays the waypoints for each route on the map.

  • Define a delegate method to handle route selection.

    1
    extension DrawAlternativeRouteController: NavigationMapViewDelegate {
    2
    // Delegate method called when the user selects a route
    3
    func navigationMapView(_ mapView: NavigationMapView, didSelect route: Route) {
    4
    guard let routes = routes else { return }
    5
    guard let index = routes.firstIndex(where: { $0 == route }) else { return }
    6
    self.routes!.remove(at: index)
    7
    self.routes!.insert(route, at: 0)
    8
    }
    9
    }

    This code defines a delegate method called navigationMapView(_:didSelect:)

© 2024 NextBillion.ai all rights reserved.