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"
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]]

View File

@ -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]))
}

View File

@ -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"

View File

@ -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

View File

@ -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<f64>,
latitude: NotNan<f64>,
}
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<f64> {
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())
}
}

View File

@ -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)
}

View File

@ -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")?;