-
Notifications
You must be signed in to change notification settings - Fork 93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Isochrone api #621
Isochrone api #621
Conversation
case (200, "NoSegment"): | ||
self = .unableToLocate | ||
case (404, "ProfileNotFound"): | ||
self = .profileNotFound | ||
case (422, "InvalidInput"): | ||
self = .invalidInput(message: message) | ||
case (429, _): | ||
self = .rateLimited(rateLimitInterval: response.rateLimitInterval, rateLimit: response.rateLimit, resetTime: response.rateLimitResetTime) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This table lists a few more codes that should get dedicated cases, but they sound like codes that would be returned by other navigation service APIs too. Some of the codes may come with structured properties alongside the message, similar to the 429 error, which would be nice to parse into associated values.
Do any codes conflict with Directions API error codes? Could they conflict in the future?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some troubles with this table. In the code I've listed all errors I managed to reproduce.
/** | ||
Options determining the primary mode of transportation for the contours. | ||
*/ | ||
public struct IsochroneProfileIdentifier: Codable, RawRepresentable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be consolidated with DirectionsProfileIdentifier unless there’s a possibility that some profile will intentionally be limited to one service or another.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a difference already: Isochrone does not support driving-traffic
profile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a limitation like that wouldn’t keep us from reusing DirectionsProfileIdentifier. We can just document the fact that the automobileAvoidingTraffic
constant can’t be used with the Isochrone class. What would be a problem is if the Isochrone API’s mapbox/driving-traffic profile behaved like the Directions API’s mapbox/driving profile or vice versa. Besides, these are only constants in an extensible enumeration: the developer is always able to specify an invalid profile identifier like mabpox/unicycling
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think it would be wise to rename DirectionsProfileIdentifier
to something more generic like ServiceProfileIdentifier
since it is used in multiple services and we are going to document it's effect on each one in code docs? That would be a breaking change.
I would like to avoid using exactly Directions<Something>
for Isochrone, plus mentioning Isochrones in it's automobileAvoidingTraffic
would also look strange.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think it would be wise to rename
DirectionsProfileIdentifier
to something more generic likeServiceProfileIdentifier
since it is used in multiple services and we are going to document it's effect on each one in code docs? That would be a breaking change.
I think it’s totally reasonable. ProfileIdentifier
should be sufficient; I don’t think it’s very likely to introduce a lot of conflicts with other libraries. We can avoid a breaking change by leaving in a type alias that’s marked as deprecated.
91ac378
to
34ffe06
Compare
/** | ||
Options determining the primary mode of transportation for the contours. | ||
*/ | ||
public struct IsochroneProfileIdentifier: Codable, RawRepresentable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a limitation like that wouldn’t keep us from reusing DirectionsProfileIdentifier. We can just document the fact that the automobileAvoidingTraffic
constant can’t be used with the Isochrone class. What would be a problem is if the Isochrone API’s mapbox/driving-traffic profile behaved like the Directions API’s mapbox/driving profile or vice versa. Besides, these are only constants in an extensible enumeration: the developer is always able to specify an invalid profile identifier like mabpox/unicycling
.
CHANGELOG.md
Outdated
@@ -6,6 +6,7 @@ | |||
* Added `RouteOptions.initialManeuverAvoidanceRadius` property to control avoidance of dangerous maneuvers when requesting a route from the Directions API. ([#609](https://github.com/mapbox/mapbox-directions-swift/pull/609)) | |||
* Added `RoadClasses.unpaved` property that enables the resulting routes to avoid unpaved roads. ([#620](https://github.com/mapbox/mapbox-directions-swift/pull/620)) | |||
* Added `RoadClasses.cashOnlyToll` property that enables the resulting routes to avoid toll roads that only accept cash payment. ([#620](https://github.com/mapbox/mapbox-directions-swift/pull/620)) | |||
* Added `Ischrone` API wrapper. The [Mapbox Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) computes areas that are reachable within a specified amount of time from a location, and returns the reachable regions as contours of polygons or lines that you can display on a map. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let’s add a basic usage example to the readme. The example can assume the presence of the map SDK or MapboxStatic.swift. This can be tail work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think an Example would be even better. Could we add it to navigation-ios-examples
? It's not related to navigation though, but looks like we don't have a dedicated place for Directions
examples at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, mapbox-navigation-ios-examples is a good place to showcase what MapboxDirections can do on its own. We should still nod to the existence of Isochrone API support in the readme though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added example usage to README
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incidentally, it never occurred to me that it’s the Isochrone API, singular. We had made a big push to name all the server APIs in the plural, but the navigation service APIs must’ve escaped notice apart from the Directions API.
* Added `Ischrone` API wrapper. The [Mapbox Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) computes areas that are reachable within a specified amount of time from a location, and returns the reachable regions as contours of polygons or lines that you can display on a map. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) | |
* Added `Isochrones`, which connects to the [Mapbox Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) to compute areas that are reachable within a specified amount of time from a location and return the reachable regions as contours of polygons or lines that you can display on a map. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) | |
* Renamed `DirectionsCredentials` and `DirectionsProfileIdentifier` to `Credentials` and `ProfileIdentifier`, respectively. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class is currently called Isochrones
, plural.
* Added `Ischrone` API wrapper. The [Mapbox Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) computes areas that are reachable within a specified amount of time from a location, and returns the reachable regions as contours of polygons or lines that you can display on a map. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) | |
* Added `Isochrones`, which connects to the [Mapbox Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) to compute areas that are reachable within a specified amount of time from a location, returning the reachable regions as contours of polygons or lines that you can display on a map. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) | |
* Renamed `DirectionsCredentials` and `DirectionsProfileIdentifier` to `Credentials` and `ProfileIdentifier`, respectively. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) |
/** | ||
Contour bound definition value and contour color. | ||
*/ | ||
public typealias ValueAndColor = (value: Value, color: Color) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My suggestion in #621 (comment) didn’t consider the possibility of specifying the color on none of the contours (which the API turns into a rainbow by default). The type system gets a bit complicated as a result. If additional per-contour properties get added in the future, such as opacity, we could be forced to make this enumeration more complicated. A struct also gives us more flexibility to maintain backwards compatibility.
What if we stick to something similar to the design in #621 (comment) but make color
optional? On the client-side, we can fill in a default color at request time if colors are specified for some contours but not others. This wouldn’t violate the API contract, because the API doesn’t allow leaving some colors unspecified in the first place. But if it does in the future, it would be trivial to remove the fallback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filling colors gap automatically seems error prone. We cannot track if API will change the default color scheme, we'll also be basically guessing which default color to substitute in each particular gap.
Since we are making an API wrapper, it should make usage convenient but not alter the original behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It’s not so much for the developer’s convenience but for us to ensure the client-side API’s flexibility:
- If the Isochrone API later introduces the ability to leave one of the colors unspecified, then the fallbacks would become extraneous, but everything the developer could previously do would remain possible, and it wouldn’t be possible to specify an invalid set of contours. On the other hand, with these tuples, we’d have to introduce a
ValueAndOptionalColor
tuple and corresponding enumeration case. - If the API adds a
contours_opacity
parameter, then we’d need to introduce new enumeration cases and tuples forValueAndColorAndOpacity
andValueAndOpacity
, and it could be combinatorial explosion after that. On the other hand, with a single struct, we can add additional optional properties without any fuss.
We could fill in black as a reasonable default color. Rainbow colors would still be possible if none of the colors is specified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Struct approach turned out 1 word shorter during initialization. I decided that using black
as a fallback color might be too much, so I chose a bit more neutral 50% gray. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some additional documentation-related nits, but I think the big question is how to structure the type system to dissuade the user from making invalid requests while being forward-compatible: #621 (comment).
let encoder = JSONEncoder() | ||
let data = try! encoder.encode(response) | ||
let geoJSONString = String(data: data, encoding: .utf8)! | ||
let geoJSONOverlay = GeoJSON(objectString: geoJSONString) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mapbox/MapboxStatic.swift#112 tracks streamlining these steps by adding Turf support to the library.
CHANGELOG.md
Outdated
@@ -6,6 +6,7 @@ | |||
* Added `RouteOptions.initialManeuverAvoidanceRadius` property to control avoidance of dangerous maneuvers when requesting a route from the Directions API. ([#609](https://github.com/mapbox/mapbox-directions-swift/pull/609)) | |||
* Added `RoadClasses.unpaved` property that enables the resulting routes to avoid unpaved roads. ([#620](https://github.com/mapbox/mapbox-directions-swift/pull/620)) | |||
* Added `RoadClasses.cashOnlyToll` property that enables the resulting routes to avoid toll roads that only accept cash payment. ([#620](https://github.com/mapbox/mapbox-directions-swift/pull/620)) | |||
* Added `Ischrone` API wrapper. The [Mapbox Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) computes areas that are reachable within a specified amount of time from a location, and returns the reachable regions as contours of polygons or lines that you can display on a map. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incidentally, it never occurred to me that it’s the Isochrone API, singular. We had made a big push to name all the server APIs in the plural, but the navigation service APIs must’ve escaped notice apart from the Directions API.
* Added `Ischrone` API wrapper. The [Mapbox Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) computes areas that are reachable within a specified amount of time from a location, and returns the reachable regions as contours of polygons or lines that you can display on a map. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) | |
* Added `Isochrones`, which connects to the [Mapbox Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) to compute areas that are reachable within a specified amount of time from a location and return the reachable regions as contours of polygons or lines that you can display on a map. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) | |
* Renamed `DirectionsCredentials` and `DirectionsProfileIdentifier` to `Credentials` and `ProfileIdentifier`, respectively. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) |
2cab7b1
to
ebc4ed1
Compare
…fier from enum to struct
… typealias; refactored IsochroneOptios.Contour and Color entities; extended tests to verify contours_minutes coding
…worked contours definition.
…for NSColor, refined contour query serialization code.
…ProfileIdentifier to reuse with Isohrones. Tests updated
… struct. Tests and examples updated
e27b811
to
c196293
Compare
CHANGELOG.md
Outdated
@@ -6,6 +6,7 @@ | |||
* Added `RouteOptions.initialManeuverAvoidanceRadius` property to control avoidance of dangerous maneuvers when requesting a route from the Directions API. ([#609](https://github.com/mapbox/mapbox-directions-swift/pull/609)) | |||
* Added `RoadClasses.unpaved` property that enables the resulting routes to avoid unpaved roads. ([#620](https://github.com/mapbox/mapbox-directions-swift/pull/620)) | |||
* Added `RoadClasses.cashOnlyToll` property that enables the resulting routes to avoid toll roads that only accept cash payment. ([#620](https://github.com/mapbox/mapbox-directions-swift/pull/620)) | |||
* Added `Ischrone` API wrapper. The [Mapbox Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) computes areas that are reachable within a specified amount of time from a location, and returns the reachable regions as contours of polygons or lines that you can display on a map. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class is currently called Isochrones
, plural.
* Added `Ischrone` API wrapper. The [Mapbox Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) computes areas that are reachable within a specified amount of time from a location, and returns the reachable regions as contours of polygons or lines that you can display on a map. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) | |
* Added `Isochrones`, which connects to the [Mapbox Isochrone API](https://docs.mapbox.com/api/navigation/isochrone/) to compute areas that are reachable within a specified amount of time from a location, returning the reachable regions as contours of polygons or lines that you can display on a map. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) | |
* Renamed `DirectionsCredentials` and `DirectionsProfileIdentifier` to `Credentials` and `ProfileIdentifier`, respectively. ([#621](https://github.com/mapbox/mapbox-directions-swift/pull/621)) |
@@ -291,7 +291,7 @@ open class DirectionsOptions: Codable { | |||
// MARK: Getting the Request URL | |||
|
|||
/** | |||
An array of URL query items to include in an HTTP request. | |||
The path of the request URL, specifying service name, version and profile. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching this!
/** | ||
Contours GeoJSON format. | ||
*/ | ||
public enum ContourFormat { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to nest this type under IsochroneOptions
? Application code might end up needing to write IsochroneOptions.ContourFormat
in some cases, but ContourFormat
on its own would probably not risk future conflicts with other API wrappers in this library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've nested this one since there's no practical use of this enum other than inside IsochroneOptions
. Cases when fully qualified name would be required for typing are pretty rare (Linux only?) since there is only 1 place (property) where it is used and it's strictly typed.
return | ||
} | ||
|
||
guard (disposition.code == nil && disposition.message == nil) || disposition.code == "Ok" else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There’s a bit of redundancy between this method and some of the Directions
methods. As tail work, we could try factoring out some common tasks so it’s easier and less error-prone to spin up support for a new API.
…s and DirectionsProfileIdentifier alieases to original implementations; code docs corrected.
Resolves #296
This PR adds
Isochrone
object to access co-named API. It's structure and tooling entities are similar toDirections
.