Skip to content

Commit

Permalink
Add LSV; richer matrix models
Browse files Browse the repository at this point in the history
  • Loading branch information
ianthetechie committed Apr 30, 2024
1 parent 0ca7298 commit 0f72f01
Show file tree
Hide file tree
Showing 17 changed files with 226 additions and 38 deletions.
21 changes: 8 additions & 13 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Created by https://www.toptal.com/developers/gitignore/api/swift,xcode
# Edit at https://www.toptal.com/developers/gitignore?templates=swift,xcode
# Created by https://www.toptal.com/developers/gitignore/api/xcode,swift
# Edit at https://www.toptal.com/developers/gitignore?templates=xcode,swift

### Swift ###
# Xcode
Expand Down Expand Up @@ -64,9 +64,9 @@ playground.xcworkspace

Carthage/Build/

# Add this lines if you are using Accio dependency management (Deprecated since Xcode 12)
# Dependencies/
# .accio/
# Accio dependency management
Dependencies/
.accio/

# fastlane
# It is recommended to not store the screenshots in the git repo.
Expand All @@ -86,23 +86,18 @@ fastlane/test_output
iOSInjectionProject/

### Xcode ###
# Xcode
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore




## Gcc Patch
/*.gcno
## Xcode 8 and earlier

### Xcode Patch ###
*.xcodeproj/*
!*.xcodeproj/project.pbxproj
!*.xcodeproj/xcshareddata/
!*.xcworkspace/contents.xcworkspacedata
/*.gcno
**/xcshareddata/WorkspaceSettings.xcsettings

# End of https://www.toptal.com/developers/gitignore/api/swift,xcode
# End of https://www.toptal.com/developers/gitignore/api/xcode,swift

## Custom additions

Expand Down
4 changes: 4 additions & 0 deletions .openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Sources/StadiaMaps/Models/LocateEdge.swift
Sources/StadiaMaps/Models/LocateEdgeInfo.swift
Sources/StadiaMaps/Models/LocateNode.swift
Sources/StadiaMaps/Models/LocateObject.swift
Sources/StadiaMaps/Models/LowSpeedVehicleCostingOptions.swift
Sources/StadiaMaps/Models/ManeuverSign.swift
Sources/StadiaMaps/Models/ManeuverSignElement.swift
Sources/StadiaMaps/Models/MapMatchCostingModel.swift
Expand All @@ -64,6 +65,7 @@ Sources/StadiaMaps/Models/MatrixCostingModel.swift
Sources/StadiaMaps/Models/MatrixDistance.swift
Sources/StadiaMaps/Models/MatrixRequest.swift
Sources/StadiaMaps/Models/MatrixResponse.swift
Sources/StadiaMaps/Models/MatrixWaypoint.swift
Sources/StadiaMaps/Models/MotorScooterCostingOptions.swift
Sources/StadiaMaps/Models/MotorcycleCostingOptions.swift
Sources/StadiaMaps/Models/NearestRoadsRequest.swift
Expand Down Expand Up @@ -150,6 +152,7 @@ docs/LocateEdge.md
docs/LocateEdgeInfo.md
docs/LocateNode.md
docs/LocateObject.md
docs/LowSpeedVehicleCostingOptions.md
docs/ManeuverSign.md
docs/ManeuverSignElement.md
docs/MapMatchCostingModel.md
Expand All @@ -162,6 +165,7 @@ docs/MatrixCostingModel.md
docs/MatrixDistance.md
docs/MatrixRequest.md
docs/MatrixResponse.md
docs/MatrixWaypoint.md
docs/MotorScooterCostingOptions.md
docs/MotorcycleCostingOptions.md
docs/NearestRoadsRequest.md
Expand Down
2 changes: 1 addition & 1 deletion .openapi-generator/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.4.0
7.5.0
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Version 3.0.0 - 2024-04-30

### Added

- Add support for low-speed vehicle routing
- The matrix endpoint now accepts its own model rather than coordinate. This includes a search cutoff and paves the way for future expansion.

### Changed

- Improved the documentation of the matrix endpoint failure modes

### Fixed

- The time and distance field on matrix source to target models are now marked as nullable

## Version 2.1.0 - 2024-03-21

### Added
Expand Down
4 changes: 2 additions & 2 deletions Sources/StadiaMaps/APIHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public enum APIHelper {
if destination.isEmpty {
return nil
}
return destination
return destination.sorted { $0.name < $1.name }
}

/// maps all values from source to query parameters
Expand All @@ -112,6 +112,6 @@ public enum APIHelper {
if destination.isEmpty {
return nil
}
return destination
return destination.sorted { $0.name < $1.name }
}
}
3 changes: 2 additions & 1 deletion Sources/StadiaMaps/Models/CostingModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
import AnyCodable
#endif

/** Costing models for determining the most optimal route to take. Note that bikeshare and motorcycle are still in beta. While Valhalla supports multimodal routing, we do not currently process transit data and have excluded it from the list. See https://valhalla.github.io/valhalla/api/turn-by-turn/api-reference/#costing-models for detailed descriptions of each model. */
/** A model which influences the routing based on the type of travel. The costing model affects parameters ranging from which roads are legally accessible to preferences based on comfort or speed. See https://valhalla.github.io/valhalla/api/turn-by-turn/api-reference/#costing-models for in-depth descriptions of each costing model. */
public enum CostingModel: String, Codable, CaseIterable {
case auto
case bus
Expand All @@ -21,4 +21,5 @@ public enum CostingModel: String, Codable, CaseIterable {
case motorScooter = "motor_scooter"
case motorcycle
case pedestrian
case lowSpeedVehicle = "low_speed_vehicle"
}
6 changes: 5 additions & 1 deletion Sources/StadiaMaps/Models/CostingOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ public struct CostingOptions: Codable, JSONEncodable, Hashable {
public var motorScooter: MotorScooterCostingOptions?
public var motorcycle: MotorcycleCostingOptions?
public var pedestrian: PedestrianCostingOptions?
public var lowSpeedVehicle: LowSpeedVehicleCostingOptions?

public init(auto: AutoCostingOptions? = nil, bus: AutoCostingOptions? = nil, taxi: AutoCostingOptions? = nil, truck: TruckCostingOptions? = nil, bicycle: BicycleCostingOptions? = nil, motorScooter: MotorScooterCostingOptions? = nil, motorcycle: MotorcycleCostingOptions? = nil, pedestrian: PedestrianCostingOptions? = nil) {
public init(auto: AutoCostingOptions? = nil, bus: AutoCostingOptions? = nil, taxi: AutoCostingOptions? = nil, truck: TruckCostingOptions? = nil, bicycle: BicycleCostingOptions? = nil, motorScooter: MotorScooterCostingOptions? = nil, motorcycle: MotorcycleCostingOptions? = nil, pedestrian: PedestrianCostingOptions? = nil, lowSpeedVehicle: LowSpeedVehicleCostingOptions? = nil) {
self.auto = auto
self.bus = bus
self.taxi = taxi
Expand All @@ -29,6 +30,7 @@ public struct CostingOptions: Codable, JSONEncodable, Hashable {
self.motorScooter = motorScooter
self.motorcycle = motorcycle
self.pedestrian = pedestrian
self.lowSpeedVehicle = lowSpeedVehicle
}

public enum CodingKeys: String, CodingKey, CaseIterable {
Expand All @@ -40,6 +42,7 @@ public struct CostingOptions: Codable, JSONEncodable, Hashable {
case motorScooter = "motor_scooter"
case motorcycle
case pedestrian
case lowSpeedVehicle = "low_speed_vehicle"
}

// Encodable protocol methods
Expand All @@ -54,5 +57,6 @@ public struct CostingOptions: Codable, JSONEncodable, Hashable {
try container.encodeIfPresent(motorScooter, forKey: .motorScooter)
try container.encodeIfPresent(motorcycle, forKey: .motorcycle)
try container.encodeIfPresent(pedestrian, forKey: .pedestrian)
try container.encodeIfPresent(lowSpeedVehicle, forKey: .lowSpeedVehicle)
}
}
110 changes: 110 additions & 0 deletions Sources/StadiaMaps/Models/LowSpeedVehicleCostingOptions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
//
// LowSpeedVehicleCostingOptions.swift
//
// Generated by openapi-generator
// https://openapi-generator.tech
//

import Foundation
#if canImport(AnyCodable)
import AnyCodable
#endif

public struct LowSpeedVehicleCostingOptions: Codable, JSONEncodable, Hashable {
public enum VehicleType: String, Codable, CaseIterable {
case lowSpeedVehicle = "low_speed_vehicle"
case golfCart = "golf_cart"
}

static let useLivingStreetsRule = NumericRule<Double>(minimum: 0, exclusiveMinimum: false, maximum: 1, exclusiveMaximum: false, multipleOf: nil)
static let useFerryRule = NumericRule<Double>(minimum: 0, exclusiveMinimum: false, maximum: 1, exclusiveMaximum: false, multipleOf: nil)
static let topSpeedRule = NumericRule<Int>(minimum: 20, exclusiveMinimum: false, maximum: 60, exclusiveMaximum: false, multipleOf: nil)
static let maxAllowedSpeedLimitRule = NumericRule<Int>(minimum: 20, exclusiveMinimum: false, maximum: 80, exclusiveMaximum: false, multipleOf: nil)
/** A penalty (in seconds) applied when transitioning between roads (determined by name). */
public var maneuverPenalty: Int? = 5
/** The estimated cost (in seconds) when a gate is encountered. */
public var gateCost: Int? = 15
/** A penalty (in seconds) applied to the route cost when a gate is encountered. This penalty can be used to reduce the likelihood of suggesting a route with gates unless absolutely necessary. */
public var gatePenalty: Int? = 300
/** The estimated cost (in seconds) when encountering an international border. */
public var countryCrossingCost: Int? = 600
/** A penalty applied to transitions to international border crossings. This penalty can be used to reduce the likelihood of suggesting a route with border crossings unless absolutely necessary. */
public var countryCrossingPenalty: Int? = 0
/** A penalty applied to transitions to service roads. This penalty can be used to reduce the likelihood of suggesting a route with service roads unless absolutely necessary. The default penalty is 15 for cars, busses, motor scooters, and motorcycles; and zero for others. */
public var servicePenalty: Int?
/** A factor that multiplies the cost when service roads are encountered. The default is 1.2 for cars and busses, and 1 for trucks, motor scooters, and motorcycles. */
public var serviceFactor: Double? = 1
/** A measure of willingness to take living streets. Values near 0 attempt to avoid them, and values near 1 will favour them. Note that as some routes may be impossible without living streets, 0 does not guarantee avoidance of them. The default value is 0 for trucks; 0.1 for other motor vehicles; 0.5 for bicycles; and 0.6 for pedestrians. */
public var useLivingStreets: Double?
/** A measure of willingness to take ferries. Values near 0 attempt to avoid ferries, and values near 1 will favour them. Note that as some routes may be impossible without ferries, 0 does not guarantee avoidance of them. */
public var useFerry: Double? = 0.5
/** If set to true, ignores any restrictions (eg: turn and conditional restrictions). Useful for matching GPS traces to the road network regardless of restrictions. */
public var ignoreRestrictions: Bool?
/** If set to true, ignores most restrictions (eg: turn and conditional restrictions), but still respects restrictions that impact vehicle safety such as weight and size. */
public var ignoreNonVehicularRestrictions: Bool?
/** If set to true, ignores directional restrictions on roads. Useful for matching GPS traces to the road network regardless of restrictions. */
public var ignoreOneways: Bool?
/** The type of vehicle: * low_speed_vehicle (BETA): a low-speed vehicle which falls under a different regulatory and licensing regime than automobiles (ex: LSV in the US and Canada, Quadricycles in the EU, etc.) * golf_cart: a street legal golf cart that is under a similar regulator regime as the generic LSV laws, but may need to follow special paths when available or abide by restrictions specific to golf carts. */
public var vehicleType: VehicleType? = .lowSpeedVehicle
/** The top speed (in kph) that the vehicle is capable of travelling. This impacts travel time calculations as well as which roads are preferred. A very low speed vehicle will tend to prefer lower speed roads even in the presence of other legal routes. */
public var topSpeed: Int? = 35
/** The maximum speed limit for highways on which it is legal for the vehicle to travel. Defaults to 57 (kph; around 35 mph). Acceptable values range from 20 to 80. Highways with *tagged* speed limits higher than this value will not be routed over (some caveats apply; this feature is still BETA). */
public var maxAllowedSpeedLimit: Int? = 57

public init(maneuverPenalty: Int? = 5, gateCost: Int? = 15, gatePenalty: Int? = 300, countryCrossingCost: Int? = 600, countryCrossingPenalty: Int? = 0, servicePenalty: Int? = nil, serviceFactor: Double? = 1, useLivingStreets: Double? = nil, useFerry: Double? = 0.5, ignoreRestrictions: Bool? = nil, ignoreNonVehicularRestrictions: Bool? = nil, ignoreOneways: Bool? = nil, vehicleType: VehicleType? = .lowSpeedVehicle, topSpeed: Int? = 35, maxAllowedSpeedLimit: Int? = 57) {
self.maneuverPenalty = maneuverPenalty
self.gateCost = gateCost
self.gatePenalty = gatePenalty
self.countryCrossingCost = countryCrossingCost
self.countryCrossingPenalty = countryCrossingPenalty
self.servicePenalty = servicePenalty
self.serviceFactor = serviceFactor
self.useLivingStreets = useLivingStreets
self.useFerry = useFerry
self.ignoreRestrictions = ignoreRestrictions
self.ignoreNonVehicularRestrictions = ignoreNonVehicularRestrictions
self.ignoreOneways = ignoreOneways
self.vehicleType = vehicleType
self.topSpeed = topSpeed
self.maxAllowedSpeedLimit = maxAllowedSpeedLimit
}

public enum CodingKeys: String, CodingKey, CaseIterable {
case maneuverPenalty = "maneuver_penalty"
case gateCost = "gate_cost"
case gatePenalty = "gate_penalty"
case countryCrossingCost = "country_crossing_cost"
case countryCrossingPenalty = "country_crossing_penalty"
case servicePenalty = "service_penalty"
case serviceFactor = "service_factor"
case useLivingStreets = "use_living_streets"
case useFerry = "use_ferry"
case ignoreRestrictions = "ignore_restrictions"
case ignoreNonVehicularRestrictions = "ignore_non_vehicular_restrictions"
case ignoreOneways = "ignore_oneways"
case vehicleType = "vehicle_type"
case topSpeed = "top_speed"
case maxAllowedSpeedLimit = "max_allowed_speed_limit"
}

// Encodable protocol methods

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(maneuverPenalty, forKey: .maneuverPenalty)
try container.encodeIfPresent(gateCost, forKey: .gateCost)
try container.encodeIfPresent(gatePenalty, forKey: .gatePenalty)
try container.encodeIfPresent(countryCrossingCost, forKey: .countryCrossingCost)
try container.encodeIfPresent(countryCrossingPenalty, forKey: .countryCrossingPenalty)
try container.encodeIfPresent(servicePenalty, forKey: .servicePenalty)
try container.encodeIfPresent(serviceFactor, forKey: .serviceFactor)
try container.encodeIfPresent(useLivingStreets, forKey: .useLivingStreets)
try container.encodeIfPresent(useFerry, forKey: .useFerry)
try container.encodeIfPresent(ignoreRestrictions, forKey: .ignoreRestrictions)
try container.encodeIfPresent(ignoreNonVehicularRestrictions, forKey: .ignoreNonVehicularRestrictions)
try container.encodeIfPresent(ignoreOneways, forKey: .ignoreOneways)
try container.encodeIfPresent(vehicleType, forKey: .vehicleType)
try container.encodeIfPresent(topSpeed, forKey: .topSpeed)
try container.encodeIfPresent(maxAllowedSpeedLimit, forKey: .maxAllowedSpeedLimit)
}
}
1 change: 1 addition & 0 deletions Sources/StadiaMaps/Models/MatrixCostingModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ public enum MatrixCostingModel: String, Codable, CaseIterable {
case motorScooter = "motor_scooter"
case motorcycle
case pedestrian
case lowSpeedVehicle = "low_speed_vehicle"
}
10 changes: 5 additions & 5 deletions Sources/StadiaMaps/Models/MatrixDistance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ import Foundation
#endif

public struct MatrixDistance: Codable, JSONEncodable, Hashable {
/** The distance (in `units`) between the location in `sources` at `from_index` and the location in `targets` at `to_index`. */
public var distance: Double
/** The travel time (in seconds) between the location in `sources` at `from_index` and the location in `targets` at `to_index`. */
public var time: Int
/** The distance (in `units`) between the location in `sources` at `from_index` and the location in `targets` at `to_index`. This value may be 0 in the case that the source and destination are the same, and `null` if no route was found between the locations. */
public var distance: Double?
/** The travel time (in seconds) between the location in `sources` at `from_index` and the location in `targets` at `to_index`. This value may be 0 in the case that the source and destination are the same, and `null` if no route was found between the locations. */
public var time: Int?
/** The index of the start location in the `sources` array. */
public var fromIndex: Int
/** The index of the end location in the `targets` array. */
public var toIndex: Int

public init(distance: Double, time: Int, fromIndex: Int, toIndex: Int) {
public init(distance: Double?, time: Int?, fromIndex: Int, toIndex: Int) {
self.distance = distance
self.time = time
self.fromIndex = fromIndex
Expand Down
6 changes: 3 additions & 3 deletions Sources/StadiaMaps/Models/MatrixRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ public struct MatrixRequest: Codable, JSONEncodable, Hashable {
/** An identifier to disambiguate requests (echoed by the server). */
public var id: String?
/** The list of starting locations */
public var sources: [Coordinate]
public var sources: [MatrixWaypoint]
/** The list of ending locations */
public var targets: [Coordinate]
public var targets: [MatrixWaypoint]
public var costing: MatrixCostingModel
public var costingOptions: CostingOptions?
/** Only applicable to one-to-many or many-to-one requests. This defaults to all locations. When specified explicitly, this option allows a partial result to be returned. This is basically equivalent to \"find the closest/best locations out of the full set.\" This can have a dramatic improvement for large requests. */
public var matrixLocations: Int?

public init(units: DistanceUnit? = nil, language: ValhallaLanguages? = nil, directionsType: DirectionsType? = .instructions, id: String? = nil, sources: [Coordinate], targets: [Coordinate], costing: MatrixCostingModel, costingOptions: CostingOptions? = nil, matrixLocations: Int? = nil) {
public init(units: DistanceUnit? = nil, language: ValhallaLanguages? = nil, directionsType: DirectionsType? = .instructions, id: String? = nil, sources: [MatrixWaypoint], targets: [MatrixWaypoint], costing: MatrixCostingModel, costingOptions: CostingOptions? = nil, matrixLocations: Int? = nil) {
self.units = units
self.language = language
self.directionsType = directionsType
Expand Down
4 changes: 2 additions & 2 deletions Sources/StadiaMaps/Models/MatrixResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import Foundation
public struct MatrixResponse: Codable, JSONEncodable, Hashable {
/** An identifier to disambiguate requests (echoed by the server). */
public var id: String?
/** The list of starting locations */
/** The list of starting locations determined by snapping to the nearest appropriate point on the road network for the costing model. All locations appear in the same order as the input. */
public var sources: [Coordinate]
/** The list of ending locations */
/** The list of ending locations determined by snapping to the nearest appropriate point on the road network for the costing model. All locations appear in the same order as the input. */
public var targets: [Coordinate]
/** The matrix of starting and ending locations, along with the computed distance and travel time. The array is row-ordered. This means that the time and distance from the first location to all others forms the first row of the array, followed by the time and distance from the second source location to all target locations, etc. */
public var sourcesToTargets: [[MatrixDistance]]
Expand Down
Loading

0 comments on commit 0f72f01

Please sign in to comment.