use crate::utils::{linear_divisor, EARTH_RADIUS_KM, wrap_to_bounds};
use crate::DistanceUnit;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Coordinate {
pub latitude: f64,
pub longitude: f64,
}
impl Coordinate {
pub fn new(lat: f64, lon: f64) -> Self {
Self {
latitude: wrap_to_bounds(lat, 90.0),
longitude: wrap_to_bounds(lon, 180.0),
}
}
pub fn in_radius(
&self,
other_coordinate: &Coordinate,
radius: f64,
distance_unit: &DistanceUnit,
) -> bool {
let distance = self.get_distance_from(other_coordinate, distance_unit);
let radius = radius * linear_divisor(distance_unit);
return distance <= radius;
}
pub fn get_distance_from(&self, other: &Coordinate, unit: &DistanceUnit) -> f64 {
let pi = std::f64::consts::PI;
let lat1 = self.latitude * pi / 180.0;
let lat2 = other.latitude * pi / 180.0;
let lon1 = self.longitude * pi / 180.0;
let lon2 = other.longitude * pi / 180.0;
let d_lon = lon2 - lon1;
let d_lat = lat2 - lat1;
let a = (((d_lat / 2.0).sin()).powi(2))
+ (lat1.cos() * lat2.cos()) * ((d_lon / 2.0).sin()).powi(2);
let c = 2.0 * (a.sqrt()).asin();
let distance_meters = (c * EARTH_RADIUS_KM) * linear_divisor(&DistanceUnit::Kilometers);
return distance_meters / linear_divisor(unit);
}
}