-
Notifications
You must be signed in to change notification settings - Fork 96
Description
The Directions API recently overloaded the exclude query parameter with an option to specify a list of point geometries in WKT format. We should add support for this syntax to serve certain use cases that require arbitrary avoidance. This would also help us achieve platform parity with the Java SDK, which implemented the feature in mapbox/mapbox-java#1362. However, it should not be implemented until the new exclude syntax leaves beta and becomes a formal part of the API contract.
Design
The overloading of exclude is particularly problematic for this library, which has always exposed exclude as an option set. But now it can hold arbitrary geometry data, which needs to be typed as a Geometry. Unfortunately, an OptionSet struct can’t store associated values, so there’s no way for us to support this syntax without breaking backwards compatibility. Besides, a geometry is semantically different than a road class.
| case roadClassesToAvoid = "exclude" |
mapbox-directions-swift/Sources/MapboxDirections/RouteOptions.swift
Lines 152 to 157 in 2b14b8c
| /** | |
| The route classes that the calculated routes will avoid. | |
| Currently, you can only specify a single road class to avoid. | |
| */ | |
| open var roadClassesToAvoid: RoadClasses = [] |
| /** | |
| Option set that contains attributes of a road segment. | |
| */ | |
| public struct RoadClasses: OptionSet, CustomStringConvertible { |
Perhaps this conflation in the API can be revisited in light of the semantic awkwardness that becomes apparent in Swift. Regardless, we can implement a parallel property, shapeToAvoid, declared as type Geometry?, with the expectation of being set to a MultiPoint until more geometry types are implemented on the server side. RouteOptions’ Codable implementation can switch between roadClassesToAvoid and shapeToAvoid depending on the value. This feature depends on Turf adding support for converting between WKT and GeoJSON: mapbox/turf-swift#185.
Workaround
Until we’re able to formally add support for this syntax, a developer can hook into the beta parameter themselves:
/**
Route options for avoiding known [pedestrian scrambles](https://en.wikipedia.org/wiki/Pedestrian_scramble).
*/
class UnscrambledRouteOptions: RouteOptions {
/// The locations of some known pedestrian scrambles to avoid.
let scrambles = MultiPoint([
.init(latitude: 39.3184214, longitude: -84.3689036),
.init(latitude: 39.3109335, longitude: -84.3798639),
.init(latitude: 37.3383465, longitude: -121.8807453),
.init(latitude: 37.3330494, longitude: -121.8796307),
])
override var urlQueryItems: [URLQueryItem] {
var items = super.urlQueryItems
let wktToAvoid = scrambles.coordinates
.map { "point(\($0.longitude) \($0.latitude)" }
.joined(separator: ",")
items.append(.init(name: "exclude", value: wktToAvoid))
return items
}
}