valhalla_client/
matrix.rs

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