diff --git a/Cargo.lock b/Cargo.lock index f14ede782c..9900c59b5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2048,6 +2048,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/convert_osm/src/srtm.rs b/convert_osm/src/srtm.rs index 0a699eb918..ea9981d8c0 100644 --- a/convert_osm/src/srtm.rs +++ b/convert_osm/src/srtm.rs @@ -39,8 +39,8 @@ impl Elevation { // TODO assert the (lon, lat) match the offsets // TODO not tons of confidence in any of this. // TODO interpolate from the 4 matching tiles? - let x = ((pt.longitude - self.lon_offset).abs() * (GRID_DIM as f64)) as usize; - let y = ((pt.latitude - self.lat_offset).abs() * (GRID_DIM as f64)) as usize; + let x = ((pt.x() - self.lon_offset).abs() * (GRID_DIM as f64)) as usize; + let y = ((pt.y() - self.lat_offset).abs() * (GRID_DIM as f64)) as usize; let i = x + (y * GRID_DIM); Distance::meters(f64::from(self.data[i])) } diff --git a/geom/Cargo.toml b/geom/Cargo.toml index db0f55315f..da7bf69c85 100644 --- a/geom/Cargo.toml +++ b/geom/Cargo.toml @@ -12,7 +12,7 @@ geo-booleanop = "0.2.0" geo-offset = "0.1.0" histogram = "0.6.9" instant = "0.1.2" -ordered-float = "1.0.1" +ordered-float = { version = "1.0.1", features=["serde"] } polylabel = { git = "https://github.com/urschrei/polylabel-rs" } serde = "1.0.98" serde_derive = "1.0.98" diff --git a/geom/src/bounds.rs b/geom/src/bounds.rs index e37475f5a5..fffe52f476 100644 --- a/geom/src/bounds.rs +++ b/geom/src/bounds.rs @@ -101,17 +101,17 @@ impl GPSBounds { } pub fn update(&mut self, pt: LonLat) { - self.min_lon = self.min_lon.min(pt.longitude); - self.max_lon = self.max_lon.max(pt.longitude); - self.min_lat = self.min_lat.min(pt.latitude); - self.max_lat = self.max_lat.max(pt.latitude); + self.min_lon = self.min_lon.min(pt.x()); + self.max_lon = self.max_lon.max(pt.x()); + self.min_lat = self.min_lat.min(pt.y()); + self.max_lat = self.max_lat.max(pt.y()); } pub fn contains(&self, pt: LonLat) -> bool { - pt.longitude >= self.min_lon - && pt.longitude <= self.max_lon - && pt.latitude >= self.min_lat - && pt.latitude <= self.max_lat + pt.x() >= self.min_lon + && pt.x() <= self.max_lon + && pt.y() >= self.min_lat + && pt.y() <= self.max_lat } // TODO cache this diff --git a/geom/src/gps.rs b/geom/src/gps.rs index 61ddac5f64..e69b3f1f13 100644 --- a/geom/src/gps.rs +++ b/geom/src/gps.rs @@ -4,27 +4,35 @@ use serde_derive::{Deserialize, Serialize}; use std::fmt; // longitude is x, latitude is y -#[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] pub struct LonLat { - pub longitude: f64, - pub latitude: f64, + longitude: NotNan, + latitude: NotNan, } impl LonLat { pub fn new(lon: f64, lat: f64) -> LonLat { LonLat { - longitude: lon, - latitude: lat, + longitude: NotNan::new(lon).unwrap(), + latitude: NotNan::new(lat).unwrap(), } } + pub fn x(self) -> f64 { + self.longitude.into_inner() + } + + pub fn y(self) -> f64 { + self.latitude.into_inner() + } + pub fn gps_dist_meters(self, other: LonLat) -> Distance { // Haversine distance let earth_radius_m = 6_371_000.0; - let lon1 = self.longitude.to_radians(); - let lon2 = other.longitude.to_radians(); - let lat1 = self.latitude.to_radians(); - let lat2 = other.latitude.to_radians(); + let lon1 = self.x().to_radians(); + let lon2 = other.x().to_radians(); + let lat1 = self.y().to_radians(); + let lat2 = other.y().to_radians(); let delta_lat = lat2 - lat1; let delta_lon = lon2 - lon1; @@ -37,21 +45,17 @@ impl LonLat { // Pretty meaningless units, for comparing distances very roughly pub fn fast_dist(self, other: LonLat) -> NotNan { - NotNan::new( - (self.longitude - other.longitude).powi(2) + (self.latitude - other.latitude).powi(2), - ) - .unwrap() + NotNan::new((self.x() - other.x()).powi(2) + (self.y() - other.y()).powi(2)).unwrap() } pub(crate) fn approx_eq(self, other: LonLat) -> bool { let epsilon = 1e-8; - (self.longitude - other.longitude).abs() < epsilon - && (self.latitude - other.latitude).abs() < epsilon + (self.x() - other.x()).abs() < epsilon && (self.y() - other.y()).abs() < epsilon } } impl fmt::Display for LonLat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "LonLat({0}, {1})", self.longitude, self.latitude) + write!(f, "LonLat({0}, {1})", self.x(), self.y()) } } diff --git a/geom/src/pt.rs b/geom/src/pt.rs index d000b21d77..09d617a0f5 100644 --- a/geom/src/pt.rs +++ b/geom/src/pt.rs @@ -50,10 +50,10 @@ impl Pt2D { (pt.x(), pt.y()) }; - let x = (gps.longitude - b.min_lon) / (b.max_lon - b.min_lon) * width; + let x = (gps.x() - b.min_lon) / (b.max_lon - b.min_lon) * width; // Invert y, so that the northernmost latitude is 0. Screen drawing order, not Cartesian // grid. - let y = height - ((gps.latitude - b.min_lat) / (b.max_lat - b.min_lat) * height); + let y = height - ((gps.y() - b.min_lat) / (b.max_lat - b.min_lat) * height); Pt2D::new(x, y) } diff --git a/map_model/src/neighborhood.rs b/map_model/src/neighborhood.rs index e6adcf8eb6..e56f0dd8dd 100644 --- a/map_model/src/neighborhood.rs +++ b/map_model/src/neighborhood.rs @@ -49,15 +49,11 @@ impl NeighborhoodBuilder { writeln!(f, "{}", self.name)?; writeln!(f, "1")?; for gps in &self.points { - writeln!(f, " {} {}", gps.longitude, gps.latitude)?; + writeln!(f, " {} {}", gps.x(), gps.y())?; } // Have to repeat the first point { - writeln!( - f, - " {} {}", - self.points[0].longitude, self.points[0].latitude - )?; + writeln!(f, " {} {}", self.points[0].x(), self.points[0].y())?; } writeln!(f, "END")?; writeln!(f, "END")?;