///|
fn validate_metric_resolution(resolution : Int) -> Result[Unit, H3Error] {
if resolution < 0 || resolution > MAX_RESOLUTION {
Err(InvalidResolution(resolution))
} else {
Ok(())
}
}
///|
/// Earth radius in kilometers, matching the H3 reference implementation.
pub const EARTH_RADIUS_KM : Double = 6371.007180918475
///|
/// Returns the total number of H3 cells at a resolution.
pub fn resolution_cell_count(resolution : Int) -> Result[UInt64, H3Error] {
match validate_metric_resolution(resolution) {
Ok(_) => ()
Err(error) => return Err(error)
}
let mut power = 1UL
let mut current = 0
while current < resolution {
power *= 7UL
current += 1
}
Ok(2UL + 120UL * power)
}
///|
/// Returns the average H3 cell area in square kilometers.
pub fn average_cell_area_km2(resolution : Int) -> Result[Double, H3Error] {
match validate_metric_resolution(resolution) {
Ok(_) => ()
Err(error) => return Err(error)
}
let areas : Array[Double] = [
4.357449416078383e+06, 6.097884417941332e+05, 8.680178039899720e+04, 1.239343465508816e+04,
1.770347654491307e+03, 2.529038581819449e+02, 3.612906216441245e+01, 5.161293359717191e+00,
7.373275975944177e-01, 1.053325134272067e-01, 1.504750190766435e-02, 2.149643129451879e-03,
3.070918756316060e-04, 4.387026794728296e-05, 6.267181135324313e-06, 8.953115907605790e-07,
]
Ok(areas[resolution])
}
///|
/// Returns the average H3 cell edge length in kilometers.
pub fn average_edge_length_km(resolution : Int) -> Result[Double, H3Error] {
match validate_metric_resolution(resolution) {
Ok(_) => ()
Err(error) => return Err(error)
}
let lengths : Array[Double] = [
1281.256011, 483.0568391, 182.5129565, 68.97922179, 26.07175968, 9.854090990,
3.724532667, 1.406475763, 0.531414010, 0.200786148, 0.075863783, 0.028663897,
0.010830188, 0.004092010, 0.001546100, 0.000584169,
]
Ok(lengths[resolution])
}
///|
/// Returns the great-circle distance between two cell centers in kilometers.
pub fn H3Index::great_circle_distance_km(
self : H3Index,
other : H3Index,
) -> Double {
let left = self.to_lat_lng()
let right = other.to_lat_lng()
let left_latitude = left.latitude() / DEGREES_PER_RADIAN
let right_latitude = right.latitude() / DEGREES_PER_RADIAN
let latitude_delta = right_latitude - left_latitude
let longitude_delta = (right.longitude() - left.longitude()) /
DEGREES_PER_RADIAN
let sin_latitude = @math.sin(latitude_delta * 0.5)
let sin_longitude = @math.sin(longitude_delta * 0.5)
let haversine = sin_latitude * sin_latitude +
@math.cos(left_latitude) *
@math.cos(right_latitude) *
sin_longitude *
sin_longitude
2.0 *
@math.atan2(haversine.sqrt(), (1.0 - haversine).sqrt()) *
EARTH_RADIUS_KM
}