use crate::constants::MAX_H3_RES;
use crate::coords::face_ijk::_geo_to_face_ijk;
use crate::h3_index::_face_ijk_to_h3;
use crate::types::{H3Error, H3Index, LatLng, H3_NULL};
pub fn lat_lng_to_cell(geo: &LatLng, res: i32) -> Result<H3Index, H3Error> {
if res < 0 || res > MAX_H3_RES {
return Err(H3Error::ResDomain);
}
if !geo.lat.is_finite()
|| !geo.lng.is_finite()
|| geo.lat.abs() > (crate::constants::M_PI_2 + crate::constants::EPSILON_RAD)
{
return Err(H3Error::LatLngDomain);
}
let mut fijk = crate::types::FaceIJK::default();
_geo_to_face_ijk(geo, res, &mut fijk);
let h = _face_ijk_to_h3(&fijk, res);
if h == H3_NULL {
Err(H3Error::Failed) } else {
Ok(h)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::h3_index; use crate::latlng::_set_geo_degs; use crate::types::H3_NULL;
#[test]
fn test_lat_lng_to_cell_res_domain() {
let mut geo = LatLng::default();
_set_geo_degs(&mut geo, 37.77, -122.4);
assert_eq!(lat_lng_to_cell(&geo, -1), Err(H3Error::ResDomain));
assert_eq!(lat_lng_to_cell(&geo, 16), Err(H3Error::ResDomain));
}
#[test]
fn test_lat_lng_to_cell_coord_domain() {
let mut geo_bad_lat = LatLng::default();
_set_geo_degs(&mut geo_bad_lat, 100.0, -122.4); assert_eq!(lat_lng_to_cell(&geo_bad_lat, 5), Err(H3Error::LatLngDomain));
let mut geo_nan_lng = LatLng {
lat: 0.0,
lng: f64::NAN,
};
assert_eq!(lat_lng_to_cell(&geo_nan_lng, 5), Err(H3Error::LatLngDomain));
let mut geo_inf_lat = LatLng {
lat: f64::INFINITY,
lng: 0.0,
};
assert_eq!(lat_lng_to_cell(&geo_inf_lat, 5), Err(H3Error::LatLngDomain));
}
#[test]
fn test_lat_lng_to_cell_known_values() {
let mut sf_city_hall = LatLng::default();
_set_geo_degs(&mut sf_city_hall, 37.779265, -122.419277);
let h_res5 = lat_lng_to_cell(&sf_city_hall, 5).unwrap();
assert_eq!(h_res5.0, 0x85283083fffffff, "SF City Hall res 5");
assert_eq!(h3_index::get_resolution(h_res5), 5);
let h_res10 = lat_lng_to_cell(&sf_city_hall, 10).unwrap();
assert_eq!(h_res10.0, 0x8a2830828767fff, "SF City Hall res 10");
assert_eq!(h3_index::get_resolution(h_res10), 10);
let mut north_pole = LatLng::default();
_set_geo_degs(&mut north_pole, 90.0, 0.0);
let h_pole_res3 = lat_lng_to_cell(&north_pole, 3).unwrap();
assert_eq!(h_pole_res3.0, 0x830326fffffffff, "North Pole res 3");
let mut south_pole = LatLng::default();
_set_geo_degs(&mut south_pole, -90.0, 0.0);
let h_spole_res4 = lat_lng_to_cell(&south_pole, 4).unwrap();
assert_eq!(h_spole_res4.0, 0x84f2939ffffffff, "South Pole res 4");
}
}