1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
use crate::costing;
use crate::shapes::ShapeFormat;
pub use crate::DateTime;
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[serde_with::skip_serializing_none]
#[derive(Serialize, Default, Debug)]
/// Matrix request
pub struct Manifest {
pub(crate) targets: Vec<Location>,
pub(crate) sources: Vec<Location>,
#[serde(flatten)]
costing: costing::Costing,
id: Option<String>,
matrix_locations: Option<u32>,
date_time: Option<DateTime>,
verbose: Option<bool>,
shape_format: Option<ShapeFormat>,
}
impl Manifest {
/// Create a builder for the matrix request
pub fn builder() -> Self {
Default::default()
}
/// Sets the source and targets of the matrix
pub fn sources_to_targets(
mut self,
sources: impl IntoIterator<Item = Location>,
targets: impl IntoIterator<Item = Location>,
) -> Self {
self.sources = sources.into_iter().collect();
self.targets = targets.into_iter().collect();
self
}
/// Configures the costing model
///
/// Valhalla's routing service uses dynamic, run-time costing to generate the route path.
/// Can be configured with different settings depending on the costing model used.
///
/// **Note:** multimodal costing is not supported for the time-distance matrix service at this time.
///
/// Default: [`costing::Costing::Auto`]
pub fn costing(mut self, costing: costing::Costing) -> Self {
self.costing = costing;
self
}
/// Name your route request.
///
/// If id is specified, the naming will be sent through to the response.
pub fn id(mut self, id: impl ToString) -> Self {
self.id = Some(id.to_string());
self
}
/// Sets the minimum number of locations that need to be found satisfying the request
///
/// Allows a partial result to be returned.
///
/// This is basically equivalent to:
/// > "find the closest or best N locations out of the full location set"
pub fn minimum_matrix_locations_count(mut self, count: u32) -> Self {
self.matrix_locations = Some(count);
self
}
/// Shortcut for configuring the arrival/departure date_time settings globally
/// instead of specifying it for each source/target.
///
/// See [`Location::date_time`] if you want a more granular API.
/// Valhalla will translate this to setting the value on all `source` locations when
/// [`DateTime::from_current_departure_time`] or [`DateTime::from_departure_time`] is used and
/// on all `target` locations when [`DateTime::from_arrival_time`].
///
/// **Note:**
/// There are important limitations to time awareness.
/// Due to algorithmic complexity, we disallow time-dependence for certain combinations
/// of date_time on locations:
/// - when there are more sources than `target`s:
/// - [`Location::date_time`] on any `source`
/// - using [`Self::date_time`] with [`DateTime::from_current_departure_time`] and [`DateTime::from_departure_time`]
/// - when there's more or equal amount of `target`s than/as `source`s
/// - [`Location::date_time`] on any `target`
/// - [`DateTime::from_arrival_time`]
pub fn date_time(mut self, date_time: DateTime) -> Self {
self.date_time = Some(date_time);
self
}
/// Modifies the verbosity of the output:
/// - `true` will output a flat list of objects for distances & durations explicitly specifying
/// the `source` & `target` indices.
/// - `false` will return more compact, nested row-major distances & durations arrays and
/// not echo `sources` and `targets`
///
/// Default: `true`
pub fn verbose_output(mut self, verbose: bool) -> Self {
self.verbose = Some(verbose);
self
}
/// Specifies the [`ShapeFormat`] for the path shape of each connection.
pub fn shape_format(mut self, shape_format: ShapeFormat) -> Self {
self.shape_format = Some(shape_format);
self
}
}
#[serde_with::skip_serializing_none]
#[derive(Serialize, Default, Clone, Copy, PartialEq, Debug)]
/// Location of a point on the map
pub struct Location {
lat: f32,
lon: f32,
#[serde(serialize_with = "super::serialize_naive_date_time_opt")]
date_time: Option<chrono::NaiveDateTime>,
}
impl From<super::Coordinate> for Location {
fn from((longitude, latitude): super::Coordinate) -> Self {
Self {
lat: latitude,
lon: longitude,
date_time: None,
}
}
}
impl Location {
/// Creates a new location from a longitude/latitude
pub fn new(longitude: f32, latitude: f32) -> Self {
Self::from((longitude, latitude))
}
/// Expected date/time for the user to be at the location in the local time zone of departure or arrival.
///
/// Offers more granularity over setting time than the global [`Manifest::date_time`].
///
/// **Note:**
/// This behaves differently for the matrix in comparison to the route API:
/// - If set on the sources and there's more targets than sources,
/// it will behave like a *"Specified departure time"* on the sources.
/// - If set on the targets and there's less targets than sources,
/// it will behave like a *"Specified arrival time"* on the targets.
///
/// **Note:**
/// There are important limitations to time awareness.
/// Due to algorithmic complexity, we disallow time-dependence for certain combinations
/// of date_time on locations:
/// - when there are more sources than `target`s:
/// - [`Location::date_time`] on any `source`
/// - using [`Self::date_time`] with [`DateTime::from_current_departure_time`] and [`DateTime::from_departure_time`]
/// - when there's more or equal amount of `target`s than/as `source`s
/// - [`Location::date_time`] on any `target`
/// - [`DateTime::from_arrival_time`]
pub fn date_time(mut self, date_time: chrono::NaiveDateTime) -> Self {
self.date_time = Some(date_time);
self
}
}
/// [`Location`] which was configured in the input
///
/// Present only in `verbose` mode. Verbosity can be set via [`Manifest::verbose_output`]
#[derive(Deserialize, Default, Clone, Copy, PartialEq, Debug)]
pub struct VerboseLocation {
/// Latitude as defined in [`super::Coordinate`]
pub lat: f32,
/// Longitude as defined in [`super::Coordinate`]
pub lon: f32,
/// time configured via [`Location::date_time`]
pub date_time: Option<chrono::NaiveDateTime>,
}
impl From<Location> for VerboseLocation {
fn from(value: Location) -> Self {
Self {
lat: value.lat,
lon: value.lon,
date_time: value.date_time,
}
}
}
impl From<VerboseLocation> for Location {
fn from(value: VerboseLocation) -> Self {
Self {
lat: value.lat,
lon: value.lon,
date_time: value.date_time,
}
}
}
#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
/// Response to the matrix request
pub enum Response {
/// Returned in `verbose` mode.
///
/// Verbosity can be set via [`Manifest::verbose_output`]
Verbose(VerboseResponse),
/// Returned in non-`verbose` mode.
///
/// Verbosity can be set via [`Manifest::verbose_output`]
Concise(ConciseResponse),
}
#[derive(Deserialize, Debug, Clone)]
/// Verbose response to the matrix request
pub struct VerboseResponse {
/// Name of the route request.
///
/// If id is specified via [`Manifest::id`] the naming will be sent through to the response.
pub id: Option<String>,
/// Algorithm used
pub algorithm: String,
/// Distance units for output.
///
/// Possible unit types are miles via [`super::Units::Imperial`] and kilometers via [`super::Units::Metric`].
///
/// Default: [`super::Units::Metric`]
pub units: super::Units,
/// This array may contain warning objects informing about deprecated request parameters, clamped values etc.
#[serde(default = "Vec::new")]
pub warnings: Vec<Value>,
/// The sources of the matrix
pub sources: Vec<VerboseLocation>,
/// The targets of the matrix
pub targets: Vec<VerboseLocation>,
/// A flat list of objects for distances & durations explicitly specifying the `source` & `target` indices.
///
/// The arrays rows are:
/// - time and distance from the first source location to all target locations,
/// - time and distance from the second source location to all target locations,
/// - etc.
pub sources_to_targets: Vec<Vec<VerboseSourceToTarget>>,
}
#[derive(Deserialize, Debug, Clone)]
/// Concise response to the matrix request
pub struct ConciseResponse {
/// Name of the route request.
///
/// If id is specified via [`Manifest::id`] the naming will be sent through to the response.
pub id: Option<String>,
/// Algorithm used
pub algorithm: String,
/// Distance units for output.
///
/// Possible unit types are miles via [`super::Units::Imperial`] and kilometers via [`super::Units::Metric`].
///
/// Default: [`super::Units::Metric`]
pub units: super::Units,
/// This array may contain warning objects informing about deprecated request parameters, clamped values etc.
#[serde(default = "Vec::new")]
pub warnings: Vec<Value>,
/// More compact, nested row-major distances & durations
///
/// The arrays rows are:
/// - time and distance from the first source location to all target locations,
/// - time and distance from the second source location to all target locations,
/// - etc.
pub sources_to_targets: ConciseSourceToTargets,
}
#[derive(Deserialize, Debug, Clone)]
/// Concise source to target
pub struct ConciseSourceToTargets {
/// The computed time between each set of points.
///
/// Time will always be `0` for
/// - the first element of the time-distance array for one_to_many,
/// - the last element in a many_to_one, and
/// - the first and last elements of a many_to_many
pub durations: Vec<Vec<u32>>,
/// The computed distance between each set of points.
///
/// Distance will always be `0.00` for
/// - the first element of the time-distance array for one_to_many,
/// - the last element in a many_to_one, and
/// - the first and last elements of a many_to_many.
pub distances: Vec<Vec<f32>>,
}
#[derive(Deserialize, Debug, Clone)]
/// Verbose source to target
pub struct VerboseSourceToTarget {
/// The computed distance between each set of points.
///
/// Distance will always be `0.00` for
/// - the first element of the time-distance array for one_to_many,
/// - the last element in a many_to_one, and
/// - the first and last elements of a many_to_many.
pub distance: f32,
/// The computed time between each set of points.
///
/// Time will always be `0` for
/// - the first element of the time-distance array for one_to_many,
/// - the last element in a many_to_one, and
/// - the first and last elements of a many_to_many
pub time: u32,
/// The destination index into the locations array
pub from_index: usize,
/// The origin index into the locations array
pub to_index: usize,
/// Timezone of when a user will arrive at this location or has to depart from the start point.
///
/// For information how to differentiate between departure/arrival time, please see [`Manifest::date_time`] or [`Location::date_time`].
///
/// This field is included only if:
/// - valhalla is build with timezone support,
/// - the time is below the settings `max_timedep_distance_matrix` or `max_timedep_distance`
/// - departure/arrival time is unspecified via [`Manifest::date_time`] or [`Location::date_time`]
///
/// Example: `"Europe/Berlin"`
pub time_zone_name: Option<String>,
/// Timezone of when a user will arrive at this location or has to depart from the start point.
///
/// For information how to differentiate between departure/arrival time, please see [`Manifest::date_time`] or [`Location::date_time`].
///
/// This field is included only if:
/// - valhalla is build with timezone support,
/// - the time is below the settings `max_timedep_distance_matrix` or `max_timedep_distance`
/// - departure/arrival time is unspecified via [`Manifest::date_time`] or [`Location::date_time`]
///
/// Example: `"+01:00"`
pub time_zone_offset: Option<String>,
/// When a user will arrive at this location or has to depart from the start point.
///
/// For information how to differentiate between departure/arrival time, please see [`Manifest::date_time`] or [`Location::date_time`].
///
/// This field is included only if:
/// - the time is below the settings `max_timedep_distance_matrix` or `max_timedep_distance`
/// - departure/arrival time is unspecified via [`Manifest::date_time`] or [`Location::date_time`]
///
/// Example: `"2024-11-07T15:26"`
pub date_time: Option<chrono::NaiveDateTime>,
}