///|
const PI : Double = 3.141592653589793
///|
const MEAN_EARTH_RADIUS_M : Double = 6371008.8
///|
pub fn deg_to_rad(deg : Double) -> Double {
deg * PI / 180.0
}
///|
pub fn rad_to_deg(rad : Double) -> Double {
rad * 180.0 / PI
}
///|
pub fn clamp_latitude(lat : Double) -> Double {
lat.clamp(min=-90.0, max=90.0)
}
///|
pub fn normalize_longitude(lon : Double) -> Double {
for x = lon; x < -180.0 || x >= 180.0; {
if x < -180.0 {
continue x + 360.0
} else {
continue x - 360.0
}
} nobreak {
x
}
}
///|
pub fn haversine_distance_m(a : GeoPoint, b : GeoPoint) -> Double {
let lat1 = deg_to_rad(a.lat)
let lat2 = deg_to_rad(b.lat)
let dlat = lat2 - lat1
let dlon = deg_to_rad(b.lon - a.lon)
let s1 = @math.sin(dlat / 2.0)
let s2 = @math.sin(dlon / 2.0)
let h = s1 * s1 + @math.cos(lat1) * @math.cos(lat2) * s2 * s2
2.0 * MEAN_EARTH_RADIUS_M * @math.asin(Double::min(1.0, h.sqrt()))
}
///|
pub fn lerp(a : Double, b : Double, t : Double) -> Double {
a + (b - a) * t
}
///|
pub fn interpolate_point(a : GeoPoint, b : GeoPoint, t : Double) -> GeoPoint {
{
lat: lerp(a.lat, b.lat, t),
lon: normalize_longitude(lerp(a.lon, b.lon, t)),
elevation_m: lerp(a.elevation_m, b.elevation_m, t),
}
}