Skip to content

Instantly share code, notes, and snippets.

@nside
Created April 21, 2021 05:27
Show Gist options
  • Save nside/cb30eccc851115668b5ab3f13c53aa2d to your computer and use it in GitHub Desktop.
Save nside/cb30eccc851115668b5ab3f13c53aa2d to your computer and use it in GitHub Desktop.
Graphhopper route client for Rust (uses reqwest)
pub type Point = [f64;3];
#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RouteResponse {
pub hints: Hints,
pub info: Info,
pub paths: Vec<Path>,
}
#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Hints {
#[serde(rename = "visited_nodes.sum")]
pub visited_nodes_sum: f64,
#[serde(rename = "visited_nodes.average")]
pub visited_nodes_average: f64,
}
#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Info {
pub copyrights: Vec<String>,
pub took: i64,
}
#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Path {
pub distance: f64,
pub weight: f64,
pub time: i64,
pub transfers: i64,
#[serde(rename = "points_encoded")]
pub points_encoded: bool,
pub bbox: Vec<f64>,
pub points: Points,
pub instructions: Vec<Instruction>,
pub legs: Vec<::serde_json::Value>,
pub details: Details,
pub ascend: f64,
pub descend: f64,
#[serde(rename = "snapped_waypoints")]
pub snapped_waypoints: SnappedWaypoints,
}
#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Points {
#[serde(rename = "type")]
pub type_field: String,
pub coordinates: Vec<Point>,
}
#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Instruction {
pub distance: f64,
pub heading: Option<f64>,
pub sign: i64,
pub interval: Vec<i64>,
pub text: String,
pub time: i64,
#[serde(rename = "street_name")]
pub street_name: String,
#[serde(rename = "exit_number")]
pub exit_number: Option<i64>,
pub exited: Option<bool>,
#[serde(rename = "turn_angle")]
pub turn_angle: Option<f64>,
#[serde(rename = "last_heading")]
pub last_heading: Option<f64>,
}
#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Details {
#[serde(rename = "road_class")]
pub road_class: Vec<(i64, i64, String)>,
#[serde(rename = "street_name")]
pub street_name: Vec<(i64, i64, String)>,
}
#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SnappedWaypoints {
#[serde(rename = "type")]
pub type_field: String,
pub coordinates: Vec<Point>,
}
#[derive(Clone, Debug)]
pub struct GraphhopperClient {
pub key: String
}
impl GraphhopperClient {
pub fn new(key: &str) -> GraphhopperClient {
GraphhopperClient {
key: key.to_string()
}
}
pub fn route(&self, points: &Vec<Point>) -> reqwest::Result<RouteResponse> {
let points: Vec<String> = points.iter().map(|p| format!("point={},{}&", p[0], p[1])).collect();
let url = format!("https://graphhopper.com/api/1//route?{}type=json&locale=en-us&vehicle=car&weighting=fastest&key={}&elevation=true&turn_costs=true&points_encoded=false&details=road_class&details=street_name", points.join(""), self.key);
println!("Fetching {}...", url);
let resp = reqwest::blocking::get(url)?
.json::<RouteResponse>()?;
Ok(resp)
}
}
@nside
Copy link
Author

nside commented Apr 21, 2021

call like this

    let gh = GraphhopperClient::new("xxx");
    let route = gh.route(&vec![[36.963557, -122.022068, 0.0], [37.803299, -122.409919, 0.0]]).expect("Unable to fetch route");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment