valhalla_client/elevation.rs
1pub use crate::shapes::ShapePoint;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5#[serde_with::skip_serializing_none]
6#[derive(Serialize, Default, Debug, PartialEq, Clone)]
7pub struct Manifest {
8 id: Option<String>,
9 height_precision: Option<HeightPrecision>,
10 range: Option<bool>,
11 resample_distance: Option<f64>,
12 shape: Option<Vec<ShapePoint>>,
13 encoded_polyline: Option<String>,
14 shape_format: Option<ShapeFormat>,
15}
16impl Manifest {
17 pub fn builder() -> Self {
18 Default::default()
19 }
20 /// Name your route request.
21 ///
22 /// If id is specified, the naming will be sent through to the response.
23 pub fn id(mut self, id: impl ToString) -> Self {
24 self.id = Some(id.to_string());
25 self
26 }
27 /// Controls whether the returned array is one-dimensional (height only, the default) or two-dimensional (range and height).
28 ///
29 /// This can be used to generate a graph along a route, because a 2D-array has values for x (the range) and y (the height) at each shape point.
30 /// Steepness or gradient can also be computed from a profile request (e.g. when range = `true`).
31 ///
32 /// Default: `false`
33 pub fn include_range(mut self) -> Self {
34 self.range = Some(true);
35 self
36 }
37 /// Specifying the distance (in meters) at which the input polyline is sampled in order to provide uniform distances between samples along the polyline.
38 pub fn resample_distance(mut self, resample_distance_meters: f64) -> Self {
39 self.resample_distance = Some(resample_distance_meters);
40 self
41 }
42 /// Allows increasing the returned precision for heights.
43 ///
44 /// The default of returning as integer values works fine for most cases.
45 /// However, when charting elevation results along a nearly flat road can lead to "stair step" changes in elevation.
46 ///
47 /// Default: [`HeightPrecision::ZeroDecimalPlaces`]
48 pub fn height_precision(mut self, height_precision: HeightPrecision) -> Self {
49 self.height_precision = Some(height_precision);
50 self
51 }
52 /// Specifies whether the polyline is encoded with
53 /// - 6 digit precision ([`ShapeFormat::Polyline6`]) or
54 /// - 5 digit precision ([`ShapeFormat::Polyline5`]).
55 ///
56 /// Default: [`ShapeFormat::Polyline6`], meaning the encoded polyline is expected to be 6 digit precision.
57 pub fn shape_format(mut self, shape_format: ShapeFormat) -> Self {
58 debug_assert!(self.shape.is_none(), "shape is set and setting the shape_format is requested. This combination does not make sense: shapes and encoded_polylines as input are mutually exclusive.");
59 self.shape_format = Some(shape_format);
60 self
61 }
62 /// Latitudes/longitudes where the elevation data is desired in decimal degrees.
63 ///
64 /// The input coordinates can come from many input sources, such as a GPS location, a point or a click on a map, a geocoding service, and so on.
65 /// The locations are visited in the order specified.
66 pub fn shape(mut self, shape: impl IntoIterator<Item = impl Into<ShapePoint>>) -> Self {
67 debug_assert!(self.shape_format.is_none(), "shape_format is set and setting a shape is requested. This combination does not make sense: shapes and encoded_polylines as input are mutually exclusive.");
68 debug_assert!(self.encoded_polyline.is_none(), "encoded_polyline is set and setting a shape is requested. This combination does not make sense: shapes and encoded_polylines as input are mutually exclusive.");
69 self.shape = Some(shape.into_iter().map(|s| s.into()).collect());
70 self
71 }
72 /// A set of polyline encoded latitude/longitude pairs of a line or shape where the elevation data is desired.
73 ///
74 /// Details on polyline encoding and decoding can be found [here](https://valhalla.github.io/valhalla/decoding/).
75 /// See [`Self::shape_format`] to set the precision of the polyline.
76 pub fn encoded_polyline(mut self, encoded_polyline: impl ToString) -> Self {
77 debug_assert!(self.shape.is_none(), "shape is set and setting the encoded_polyline is requested. This combination does not make sense: shapes and encoded_polylines as input are mutually exclusive.");
78 self.encoded_polyline = Some(encoded_polyline.to_string());
79 self
80 }
81}
82
83/// Specifies the precision (number of decimal places) of all returned height values.
84#[derive(serde_repr::Serialize_repr, Debug, Clone, Copy, PartialEq, Eq, Default)]
85#[repr(u8)]
86pub enum HeightPrecision {
87 /// Zero decimal places (="integer precision") of precision for all height values
88 ///
89 /// Example: `123`
90 #[default]
91 ZeroDecimalPlaces = 0,
92 /// One decimal places of precision for all height values
93 ///
94 /// Example: `123.3`
95 OneDecimalPlace,
96 /// Two decimal places of precision for all height values
97 ///
98 /// Example: `123.34`
99 TwoDecimalPlaces,
100}
101
102#[derive(Serialize, Debug, Clone, Copy, PartialEq, Eq, Default)]
103pub enum ShapeFormat {
104 /// polyline is encoded with 6 digit precision
105 #[serde(rename = "polyline6")]
106 #[default]
107 Polyline6,
108 /// polyline is encoded with 5 digit precision
109 #[serde(rename = "polyline5")]
110 Polyline5,
111}
112
113#[derive(Deserialize, Debug, Clone)]
114pub struct Response {
115 /// Name of the route request.
116 ///
117 /// If id is specified via [`Manifest::id`] the naming will be sent through to the response.
118 pub id: Option<String>,
119 /// The specified shape coordinates from the input request.
120 ///
121 /// `None` if requested enabled via [`Manifest::shape`]
122 pub shape: Option<Vec<ShapePoint>>,
123 /// The specified encoded polyline, with six degrees of precision, coordinates from the input request.
124 ///
125 /// `None` if requested enabled via [`Manifest::encoded_polyline`]
126 pub encoded_polyline: Option<String>,
127 /// The 2D array of range (x) and height (y) per input latitude, longitude coordinate.
128 ///
129 /// `None` if not enabled via [`Manifest::include_range`]
130 pub range_height: Vec<Option<(f64, Option<f64>)>>,
131 /// The range or distance along the input locations.
132 ///
133 /// It is the cumulative distance along the previous latitiude, longitude coordinates up to the current coordinate.
134 /// The x-value for the first coordinate in the shape will always be 0.
135 pub x_coordinate: Option<f64>,
136 /// The height or elevation of the associated latitude, longitude pair.
137 ///
138 /// The height is returned as null if no height data exists for a given location.
139 pub y_coordinate: Option<f64>,
140 /// An array of height for the associated latitude, longitude coordinates.
141 #[serde(default = "Vec::new")]
142 pub height: Vec<f32>,
143 /// This array may contain warning objects informing about deprecated
144 /// - request parameters,
145 /// - clamped values
146 /// - etc.
147 #[serde(default = "Vec::new")]
148 pub warnings: Vec<Value>,
149}
150
151#[cfg(test)]
152mod tests {
153 use super::*;
154 #[test]
155 fn serialisation() {
156 let manifest = Manifest::builder();
157 assert_eq!(
158 serde_json::to_value(&manifest).unwrap(),
159 serde_json::json!({})
160 );
161 }
162
163 #[test]
164 fn test_serialize_encoded_polyline() {
165 let manifest = Manifest::builder()
166 .id("some_id")
167 .height_precision(HeightPrecision::OneDecimalPlace)
168 .include_range()
169 .encoded_polyline("polyline")
170 .shape_format(ShapeFormat::Polyline6);
171 assert_eq!(
172 serde_json::to_value(&manifest).unwrap(),
173 serde_json::json!({"id":"some_id","height_precision":1,"range":true,"encoded_polyline":"polyline","shape_format":"polyline6"})
174 );
175 }
176}