Skip to content

Commit 2dec3ec

Browse files
author
Bobby Sudekum
authored
Merge pull request #145 from mapbox/routable
Add routable points option and parse results
2 parents b078f41 + f1ef7db commit 2dec3ec

File tree

5 files changed

+80
-2
lines changed

5 files changed

+80
-2
lines changed

MapboxGeocoder/MBGeocodeOptions.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ open class GeocodeOptions: NSObject {
6464
*/
6565
@objc open var locale: Locale?
6666

67+
68+
/**
69+
A Boolean value that determines whether the resulting placemarks have the `Placemark.routableLocation` property set.
70+
*/
71+
@objc open var includesRoutableLocations: Bool = false
72+
6773
fileprivate override init() {
6874
self.maximumResultCount = 0
6975
super.init()
@@ -101,6 +107,9 @@ open class GeocodeOptions: NSObject {
101107
if let languageCode = (locale as NSLocale?)?.object(forKey: .languageCode) as? String {
102108
params.append(URLQueryItem(name: "language", value: languageCode))
103109
}
110+
111+
params.append(URLQueryItem(name: "routing", value: String(describing: includesRoutableLocations)))
112+
104113
return params
105114
}
106115
}

MapboxGeocoder/MBGeocoder.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ extension CLLocationCoordinate2D {
7070
/**
7171
Initializes a coordinate pair based on the given GeoJSON array.
7272
*/
73-
internal init(geoJSON array: [Double]) {
73+
internal init(geoJSON array: [CLLocationDegrees]) {
7474
assert(array.count == 2)
7575
self.init(latitude: array[1], longitude: array[0])
7676
}
@@ -83,6 +83,13 @@ extension CLLocation {
8383
internal convenience init(coordinate: CLLocationCoordinate2D) {
8484
self.init(latitude: coordinate.latitude, longitude: coordinate.longitude)
8585
}
86+
87+
/**
88+
Returns a GeoJSON compatible array of coordinates.
89+
*/
90+
internal func geojson() -> [CLLocationDegrees] {
91+
return [coordinate.longitude, coordinate.latitude]
92+
}
8693
}
8794

8895
/**

MapboxGeocoder/MBPlacemark.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,12 +385,71 @@ internal struct Properties: Codable {
385385
let category: String?
386386
}
387387

388+
// Used internally for flattening and transforming routable_points.points.coordinates
389+
internal struct RoutableLocation: Codable {
390+
internal let coordinates: [Double]
391+
392+
internal var coordinate: CLLocationCoordinate2D? {
393+
if coordinates.count >= 2 {
394+
return CLLocationCoordinate2D(latitude: coordinates[1], longitude: coordinates[0])
395+
}
396+
return nil
397+
}
398+
}
399+
388400
/**
389401
A concrete subclass of `Placemark` to represent results of geocoding requests.
390402
*/
391403
@objc(MBGeocodedPlacemark)
392404
open class GeocodedPlacemark: Placemark {
393405

406+
private enum CodingKeys: String, CodingKey {
407+
case routableLocations = "routable_points"
408+
}
409+
410+
private enum PointsCodingKeys: String, CodingKey {
411+
case points
412+
}
413+
414+
/**
415+
An array of locations that serve as hints for navigating to the placemark.
416+
417+
If the `GeocodeOptions.includesRoutableLocations` property is set to `true`, this property contains locations that are suitable to use as a waypoint in a routing engine such as MapboxDirections.swift. Otherwise, if the `GeocodeOptions.includesRoutableLocations` property is set to `false`, this property is set to `nil`.
418+
419+
For the placemark’s geographic center, use the `location` property. The routable locations may differ from the geographic center. For example, if a house’s driveway leads to a street other than the nearest street (by straight-line distance), then this property may contain the location where the driveway meets the street. A route to the placemark’s geographic center may be impassable, but a route to the routable location would end on the correct street with access to the house.
420+
*/
421+
@objc open var routableLocations: [CLLocation]?
422+
423+
public required init(from decoder: Decoder) throws {
424+
try super.init(from: decoder)
425+
426+
let container = try decoder.container(keyedBy: CodingKeys.self)
427+
428+
if let pointsContainer = try? container.nestedContainer(keyedBy: PointsCodingKeys.self, forKey: .routableLocations),
429+
var coordinatesContainer = try? pointsContainer.nestedUnkeyedContainer(forKey: .points) {
430+
431+
if let routableLocation = try coordinatesContainer.decodeIfPresent(RoutableLocation.self),
432+
let coordinate = routableLocation.coordinate {
433+
routableLocations = [CLLocation(coordinate: coordinate)]
434+
}
435+
}
436+
}
437+
438+
public override func encode(to encoder: Encoder) throws {
439+
try super.encode(to: encoder)
440+
441+
var container = encoder.container(keyedBy: CodingKeys.self)
442+
443+
if let routableLocations = routableLocations,
444+
!routableLocations.isEmpty {
445+
var pointsContainer = container.nestedContainer(keyedBy: PointsCodingKeys.self, forKey: .routableLocations)
446+
var coordinatesContainer = pointsContainer.nestedUnkeyedContainer(forKey: .points)
447+
let routableLocation = RoutableLocation(coordinates: [routableLocations[0].coordinate.longitude,
448+
routableLocations[0].coordinate.latitude])
449+
try coordinatesContainer.encode(routableLocation)
450+
}
451+
}
452+
394453
@objc open override var debugDescription: String {
395454
return qualifiedName!
396455
}

MapboxGeocoderTests/ForwardGeocodingTests.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class ForwardGeocodingTests: XCTestCase {
3939
XCTAssertEqual(task.state, URLSessionTask.State.completed)
4040
}
4141

42+
XCTAssertEqual(addressPlacemark.routableLocations![0].coordinate.longitude, CLLocationDegrees(138.995284))
43+
XCTAssertEqual(addressPlacemark.routableLocations![0].coordinate.latitude, CLLocationDegrees(-34.470403))
44+
4245
XCTAssertEqual(addressPlacemark.description, "Pennsylvania Ave", "forward geocode should populate description")
4346
XCTAssertEqual(addressPlacemark.debugDescription, "Pennsylvania Ave, Wasaga Beach, Ontario L9Z 3A8, Canada", "forward geocode should populate debug description")
4447
XCTAssertEqual(addressPlacemark.name, "Pennsylvania Ave", "forward geocode should populate name")
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"type":"FeatureCollection","query":["1600","pennsylvania","ave"],"features":[{"id":"address.10133733172573100","type":"Feature","text":"Pennsylvania Ave","place_name":"Pennsylvania Ave, Wasaga Beach, Ontario L9Z 3A8, Canada","relevance":0.39,"properties":{},"center":[-79.9850737,44.5047077],"geometry":{"type":"Point","coordinates":[-79.9850737,44.5047077]},"context":[{"id":"place.655624","text":"Wasaga Beach","wikidata":"Q3047234"},{"id":"postcode.17609609551414490","text":"L9Z 3A8"},{"id":"region.13373639426376420","text":"Ontario","short_code":"CA-ON","wikidata":"Q1904"},{"id":"country.15589894856372040","text":"Canada","short_code":"ca","wikidata":null}]},{"id":"address.6485281316573100","type":"Feature","text":"Pennsylvania Ave","place_name":"Pennsylvania Ave, Vaughan, Ontario L4K 3X6, Canada","relevance":0.39,"properties":{},"center":[-79.532497,43.802232],"geometry":{"type":"Point","coordinates":[-79.532497,43.802232]},"context":[{"id":"neighborhood.5043724752221980","text":"Vellore Woods"},{"id":"place.646758","text":"Vaughan","wikidata":"Q44013"},{"id":"postcode.6385804433309570","text":"L4K 3X6"},{"id":"region.13373639426376420","text":"Ontario","short_code":"CA-ON","wikidata":"Q1904"},{"id":"country.15589894856372040","text":"Canada","short_code":"ca","wikidata":"Q16"}]},{"id":"address.12769812476573100","type":"Feature","text":"Pennsylvania Ave","place_name":"Pennsylvania Ave, Stellarton, Nova Scotia B0K 1S0, Canada","relevance":0.39,"properties":{},"center":[-62.661376,45.556068],"geometry":{"type":"Point","coordinates":[-62.661376,45.556068]},"context":[{"id":"place.593196","text":"Stellarton","wikidata":"Q3498168"},{"id":"postcode.13310912212063190","text":"B0K 1S0"},{"id":"region.10539239752558240","text":"Nova Scotia","short_code":"CA-NS","wikidata":" Q10116"},{"id":"country.15589894856372040","text":"Canada","short_code":"ca","wikidata":null}]},{"id":"address.6456604709573100","type":"Feature","text":"Pennsylvania Ave","place_name":"Pennsylvania Ave, Vaughan, Ontario L4K 3X8, Canada","relevance":0.39,"properties":{},"center":[-79.531684,43.802706],"geometry":{"type":"Point","coordinates":[-79.531684,43.802706]},"context":[{"id":"neighborhood.5043724752221980","text":"Vellore Woods"},{"id":"place.646758","text":"Vaughan","wikidata":"Q44013"},{"id":"postcode.6367605302663760","text":"L4K 3X8"},{"id":"region.13373639426376420","text":"Ontario","short_code":"CA-ON","wikidata":null},{"id":"country.15589894856372040","text":"Canada","short_code":"ca","wikidata":"Q16"}]}],"attribution":"NOTICE: © 2016 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}
1+
{"type":"FeatureCollection","query":["1600","pennsylvania","ave"],"features":[{"id":"address.10133733172573100","type":"Feature","text":"Pennsylvania Ave","place_name":"Pennsylvania Ave, Wasaga Beach, Ontario L9Z 3A8, Canada","relevance":0.39,"properties":{},"center":[-79.9850737,44.5047077],"routable_points":{"points":[{"coordinates":[138.995284,-34.470403]}]},"geometry":{"type":"Point","coordinates":[-79.9850737,44.5047077]},"context":[{"id":"place.655624","text":"Wasaga Beach","wikidata":"Q3047234"},{"id":"postcode.17609609551414490","text":"L9Z 3A8"},{"id":"region.13373639426376420","text":"Ontario","short_code":"CA-ON","wikidata":"Q1904"},{"id":"country.15589894856372040","text":"Canada","short_code":"ca","wikidata":null}]},{"id":"address.6485281316573100","type":"Feature","text":"Pennsylvania Ave","place_name":"Pennsylvania Ave, Vaughan, Ontario L4K 3X6, Canada","relevance":0.39,"properties":{},"center":[-79.532497,43.802232],"geometry":{"type":"Point","coordinates":[-79.532497,43.802232]},"context":[{"id":"neighborhood.5043724752221980","text":"Vellore Woods"},{"id":"place.646758","text":"Vaughan","wikidata":"Q44013"},{"id":"postcode.6385804433309570","text":"L4K 3X6"},{"id":"region.13373639426376420","text":"Ontario","short_code":"CA-ON","wikidata":"Q1904"},{"id":"country.15589894856372040","text":"Canada","short_code":"ca","wikidata":"Q16"}]},{"id":"address.12769812476573100","type":"Feature","text":"Pennsylvania Ave","place_name":"Pennsylvania Ave, Stellarton, Nova Scotia B0K 1S0, Canada","relevance":0.39,"properties":{},"center":[-62.661376,45.556068],"geometry":{"type":"Point","coordinates":[-62.661376,45.556068]},"context":[{"id":"place.593196","text":"Stellarton","wikidata":"Q3498168"},{"id":"postcode.13310912212063190","text":"B0K 1S0"},{"id":"region.10539239752558240","text":"Nova Scotia","short_code":"CA-NS","wikidata":" Q10116"},{"id":"country.15589894856372040","text":"Canada","short_code":"ca","wikidata":null}]},{"id":"address.6456604709573100","type":"Feature","text":"Pennsylvania Ave","place_name":"Pennsylvania Ave, Vaughan, Ontario L4K 3X8, Canada","relevance":0.39,"properties":{},"center":[-79.531684,43.802706],"geometry":{"type":"Point","coordinates":[-79.531684,43.802706]},"context":[{"id":"neighborhood.5043724752221980","text":"Vellore Woods"},{"id":"place.646758","text":"Vaughan","wikidata":"Q44013"},{"id":"postcode.6367605302663760","text":"L4K 3X8"},{"id":"region.13373639426376420","text":"Ontario","short_code":"CA-ON","wikidata":null},{"id":"country.15589894856372040","text":"Canada","short_code":"ca","wikidata":"Q16"}]}],"attribution":"NOTICE: © 2016 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}

0 commit comments

Comments
 (0)