mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 23:15:24 +03:00
make LonLat implement Eq
This commit is contained in:
parent
55e0d2a364
commit
65ef5d4149
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -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]]
|
||||
|
@ -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]))
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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")?;
|
||||
|
Loading…
Reference in New Issue
Block a user