///|
const EARTH_RADIUS_M : Double = 6371008.8
///|
pub fn haversine_meters(a : Point, b : Point) -> Result[Double, RouteError] {
match validate_point(a, 0) {
Ok(_) => ()
Err(err) => return Err(err)
}
match validate_point(b, 1) {
Ok(_) => ()
Err(err) => return Err(err)
}
let lat1 = deg_to_rad(a.lat)
let lat2 = deg_to_rad(b.lat)
let dlat = deg_to_rad(b.lat - a.lat)
let dlon = deg_to_rad(b.lon - a.lon)
let sin_lat = @math.sin(dlat / 2.0)
let sin_lon = @math.sin(dlon / 2.0)
let h = sin_lat * sin_lat +
@math.cos(lat1) * @math.cos(lat2) * sin_lon * sin_lon
let clamped = h.clamp(min=0.0, max=1.0)
let central = 2.0 * @math.atan2(clamped.sqrt(), (1.0 - clamped).sqrt())
Ok(EARTH_RADIUS_M * central)
}
///|
pub fn route_distance_meters(
points : ArrayView[Point],
) -> Result[Double, RouteError] {
match require_points(points) {
Ok(_) => ()
Err(err) => return Err(err)
}
if points.length() < 2 {
return Ok(0.0)
}
let mut total = 0.0
for i in 1.. total = total + distance
Err(err) => return Err(err)
}
}
Ok(total)
}
///|
pub fn bounding_box(points : ArrayView[Point]) -> Result[BBox, RouteError] {
match require_points(points) {
Ok(_) => ()
Err(err) => return Err(err)
}
let first = points[0]
let mut min_lat = first.lat
let mut min_lon = first.lon
let mut max_lat = first.lat
let mut max_lon = first.lon
for i in 1.. max_lat {
max_lat = point.lat
}
if point.lon > max_lon {
max_lon = point.lon
}
}
Ok({ min_lat, min_lon, max_lat, max_lon })
}
///|
pub fn BBox::center(self : BBox) -> Point {
Point(
(self.min_lat + self.max_lat) / 2.0,
(self.min_lon + self.max_lon) / 2.0,
)
}