use std::ops::Sub;
static EARTH_RADIUS: f64 = 6371.009;
#[derive(Default, Clone, Copy, PartialEq)]
pub struct GeoLocation {
pub latitude: f64,
pub longitude: f64
}
impl GeoLocation {
pub fn new() -> GeoLocation {
GeoLocation {
latitude: 0.0,
longitude: 0.0
}
}
pub fn from_coordinates(latitude: f64, longitude: f64) -> GeoLocation {
assert!(latitude.abs()<=90.0);
assert!(longitude.abs()<=180.0);
GeoLocation {
latitude: latitude,
longitude: longitude
}
}
pub fn distance_to(&self, other: &GeoLocation) -> f64 {
let lat1 = self.latitude.to_radians();
let lat2 = other.latitude.to_radians();
let dlat = (other.latitude - self.latitude).to_radians();
let dlon = (other.longitude - self.longitude).to_radians();
let a = (dlat / 2.0).sin() * (dlat / 2.0).sin() +
lat1.cos() * lat2.cos() *
(dlon / 2.0).sin() * (dlon / 2.0).sin();
let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());
EARTH_RADIUS * c
}
}
impl Sub<GeoLocation> for GeoLocation {
type Output = f64;
fn sub(self, rhs: GeoLocation) -> f64 {
self.distance_to(&rhs)
}
}