Closed MalcolmScoffable closed 3 years ago
PolyLineString is an intermediate container that allows the same class to contain either a polyline-encoded string or GeoJSON geometry. The precision is an associated value of the polyline case, but the type itself is incapable of persisting the precision because it isn’t explicitly stated in that part of the API response. For that reason, the struct relies on encoding options to influence the decoding interpretation.
As long as your route options object specifies shapeFormat
as polyline6
, the decoded PolyLineString should respect that setting. Is that not the case in your experience?
Hi there, This isn't my experience. When trying to serialize the polyline directions to JSON it always defaults to serializing in polyline 5, even if the original shape format was set to polyline 6. My route options specify Polyline 6 as the shapeformat in all cases. I've tried tracing this through what's actually happening, and from what I can see serialising directions always defaults to polyline 5 regardless of what's set in the route options.
I may be misunderstanding the code a little, but this seems problematic to me in that there is no reference to the config set in the route options: https://github.com/mapbox/mapbox-directions-swift/blob/bbe54bc196e71f9603ecdde50fa125d27785bc5c/Sources/MapboxDirections/Extensions/Codable.swift#L63
Here’s the code path that results in the precision being preserved when re-encoding a RouteStep (or, by extension, a RouteLeg or Route):
https://github.com/mapbox/mapbox-directions-swift/blob/25fd495147916c3beaafaff621638e5061dd14c2/Sources/MapboxDirections/RouteStep.swift#L526 https://github.com/mapbox/mapbox-directions-swift/blob/25fd495147916c3beaafaff621638e5061dd14c2/Sources/MapboxDirections/Extensions/Codable.swift#L33-L34 https://github.com/mapbox/mapbox-directions-swift/blob/25fd495147916c3beaafaff621638e5061dd14c2/Sources/MapboxDirections/Extensions/Codable.swift#L20
Therefore, the precision is already baked into the encodedPolyline
by the time we get here; the precision
associated value is redundant:
Granted, if you were to re-encode a PolyLineString in isolation, the precision would be lost. After re-encoding the PolyLineString, if you want to decode it again, you need to provide the route options in the user info dictionary so that the decoder knows the precision to use. It’s quite unfortunate that the polyline and precision are decoupled like this, but it’s an unavoidable consequence of how the Directions API response is structured. This library often departs from the Directions API response in terms of the Swift representation but doesn’t have leeway to depart from it in terms of the JSON representation that it re-encodes.
Sorry for the late response.
I'm not sure I fully understand this, but are you saying that if the option is provided to the encoder then the directions will be re-encoded using the specified precision?
My code for re-encoding the route is as follows:
let jsonEncoder = JSONEncoder()
jsonEncoder.userInfo[.options] = DriverNavigationManager.sharedInstance().routeOptions
let jsonData = try JSONEncoder().encode(self)
let jsonRouteString = String(data: jsonData, encoding: String.Encoding.utf8)
This gives me the route in JSON, but all polylines are encoded in polyline 5. I do explicitly set the route options to use polyline 6. I may be doing this incorrectly however, but really can't see what the correct set of options would be.
are you saying that if the option is provided to the encoder then the directions will be re-encoded using the specified precision?
Yes, that’s correct regarding RouteStep or an object that contains it, like Route. The decoded polyline is only ever stored in memory as a series of numeric coordinates, so RouteStep’s Codable implementation relies on the RouteOptions object for that extra bit of context about precision.
The problem seems to be that you’re setting the user info dictionary on one JSONEncoder instance but encoding self using a different JSONEncoder instance. This modified version of your code should behave correctly:
let jsonEncoder = JSONEncoder()
jsonEncoder.userInfo[.options] = DriverNavigationManager.sharedInstance().routeOptions
let jsonData = try jsonEncoder.encode(self)
let jsonRouteString = String(data: jsonData, encoding: String.Encoding.utf8)
Ah, my mistake. It's obvious now that you've pointed the above out. I've updated my code and can confirm this works fine. Thanks very much.
Closing this issue as not a problem (see comments in issue for resolution).
SDK versions: v1.2.0 and v2.0.0-alpha.2 Swift version: 5
I've noticed a problem in re-encoding a route object in that polylines are always re-encoded in polyline5 shape format rather than honouring the encoding that was used in the original route data, or using any config passed into the encoder. I've got a situation where I want to re-encode a route object to JSON. I was expecting this to be encoded in the same form as the original route (using polyline6), however polyline5 is always used instead. Having drilled into the code I can't see a way of actually changing the encoder to use polyline6.
I can't tell if I'm missing something here, or if this is a bug, or intentionally so. This function does not appear to use any provided config however: https://github.com/mapbox/mapbox-directions-swift/blob/bbe54bc196e71f9603ecdde50fa125d27785bc5c/Sources/MapboxDirections/Extensions/Codable.swift#L57
As an example, the way I'm trying to encode the route is as follows:
Totally accept that I may be doing something incorrectly here, but this has had me rather confused. I've also not seen any related issues.
Any ideas on this would be appreciated. I've looked into attempting to fix the code to honour the provided config. However, this does appear to run quite deep and I haven't succeeded in this yet.