make LonLat implement Eq

This commit is contained in:
Dustin Carlino 2020-04-24 21:36:52 -07:00
parent 55e0d2a364
commit 65ef5d4149
7 changed files with 36 additions and 35 deletions

1
Cargo.lock generated
View File

@ -2048,6 +2048,7 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]

View File

@ -39,8 +39,8 @@ impl Elevation {
// TODO assert the (lon, lat) match the offsets // TODO assert the (lon, lat) match the offsets
// TODO not tons of confidence in any of this. // TODO not tons of confidence in any of this.
// TODO interpolate from the 4 matching tiles? // TODO interpolate from the 4 matching tiles?
let x = ((pt.longitude - self.lon_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.latitude - self.lat_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); let i = x + (y * GRID_DIM);
Distance::meters(f64::from(self.data[i])) Distance::meters(f64::from(self.data[i]))
} }

View File

@ -12,7 +12,7 @@ geo-booleanop = "0.2.0"
geo-offset = "0.1.0" geo-offset = "0.1.0"
histogram = "0.6.9" histogram = "0.6.9"
instant = "0.1.2" 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" } polylabel = { git = "https://github.com/urschrei/polylabel-rs" }
serde = "1.0.98" serde = "1.0.98"
serde_derive = "1.0.98" serde_derive = "1.0.98"

View File

@ -101,17 +101,17 @@ impl GPSBounds {
} }
pub fn update(&mut self, pt: LonLat) { pub fn update(&mut self, pt: LonLat) {
self.min_lon = self.min_lon.min(pt.longitude); self.min_lon = self.min_lon.min(pt.x());
self.max_lon = self.max_lon.max(pt.longitude); self.max_lon = self.max_lon.max(pt.x());
self.min_lat = self.min_lat.min(pt.latitude); self.min_lat = self.min_lat.min(pt.y());
self.max_lat = self.max_lat.max(pt.latitude); self.max_lat = self.max_lat.max(pt.y());
} }
pub fn contains(&self, pt: LonLat) -> bool { pub fn contains(&self, pt: LonLat) -> bool {
pt.longitude >= self.min_lon pt.x() >= self.min_lon
&& pt.longitude <= self.max_lon && pt.x() <= self.max_lon
&& pt.latitude >= self.min_lat && pt.y() >= self.min_lat
&& pt.latitude <= self.max_lat && pt.y() <= self.max_lat
} }
// TODO cache this // TODO cache this

View File

@ -4,27 +4,35 @@ use serde_derive::{Deserialize, Serialize};
use std::fmt; use std::fmt;
// longitude is x, latitude is y // 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 struct LonLat {
pub longitude: f64, longitude: NotNan<f64>,
pub latitude: f64, latitude: NotNan<f64>,
} }
impl LonLat { impl LonLat {
pub fn new(lon: f64, lat: f64) -> LonLat { pub fn new(lon: f64, lat: f64) -> LonLat {
LonLat { LonLat {
longitude: lon, longitude: NotNan::new(lon).unwrap(),
latitude: lat, 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 { pub fn gps_dist_meters(self, other: LonLat) -> Distance {
// Haversine distance // Haversine distance
let earth_radius_m = 6_371_000.0; let earth_radius_m = 6_371_000.0;
let lon1 = self.longitude.to_radians(); let lon1 = self.x().to_radians();
let lon2 = other.longitude.to_radians(); let lon2 = other.x().to_radians();
let lat1 = self.latitude.to_radians(); let lat1 = self.y().to_radians();
let lat2 = other.latitude.to_radians(); let lat2 = other.y().to_radians();
let delta_lat = lat2 - lat1; let delta_lat = lat2 - lat1;
let delta_lon = lon2 - lon1; let delta_lon = lon2 - lon1;
@ -37,21 +45,17 @@ impl LonLat {
// Pretty meaningless units, for comparing distances very roughly // Pretty meaningless units, for comparing distances very roughly
pub fn fast_dist(self, other: LonLat) -> NotNan<f64> { pub fn fast_dist(self, other: LonLat) -> NotNan<f64> {
NotNan::new( NotNan::new((self.x() - other.x()).powi(2) + (self.y() - other.y()).powi(2)).unwrap()
(self.longitude - other.longitude).powi(2) + (self.latitude - other.latitude).powi(2),
)
.unwrap()
} }
pub(crate) fn approx_eq(self, other: LonLat) -> bool { pub(crate) fn approx_eq(self, other: LonLat) -> bool {
let epsilon = 1e-8; let epsilon = 1e-8;
(self.longitude - other.longitude).abs() < epsilon (self.x() - other.x()).abs() < epsilon && (self.y() - other.y()).abs() < epsilon
&& (self.latitude - other.latitude).abs() < epsilon
} }
} }
impl fmt::Display for LonLat { impl fmt::Display for LonLat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 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())
} }
} }

View File

@ -50,10 +50,10 @@ impl Pt2D {
(pt.x(), pt.y()) (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 // Invert y, so that the northernmost latitude is 0. Screen drawing order, not Cartesian
// grid. // 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) Pt2D::new(x, y)
} }

View File

@ -49,15 +49,11 @@ impl NeighborhoodBuilder {
writeln!(f, "{}", self.name)?; writeln!(f, "{}", self.name)?;
writeln!(f, "1")?; writeln!(f, "1")?;
for gps in &self.points { for gps in &self.points {
writeln!(f, " {} {}", gps.longitude, gps.latitude)?; writeln!(f, " {} {}", gps.x(), gps.y())?;
} }
// Have to repeat the first point // Have to repeat the first point
{ {
writeln!( writeln!(f, " {} {}", self.points[0].x(), self.points[0].y())?;
f,
" {} {}",
self.points[0].longitude, self.points[0].latitude
)?;
} }
writeln!(f, "END")?; writeln!(f, "END")?;
writeln!(f, "END")?; writeln!(f, "END")?;