use crate::constants::BASE32;
pub fn encode(lat: f64, lng: f64, precision: usize) -> String {
let mut z_coordinate = Vec::with_capacity(60);
let mut lat_interval = (-90.0, 90.0);
let mut lon_interval = (-180.0, 180.0);
for _ in 0..60 {
let mid = (lon_interval.0 + lon_interval.1) / 2.0;
if lng > mid {
z_coordinate.push(1);
lon_interval.0 = mid;
} else {
z_coordinate.push(0);
lon_interval.1 = mid;
}
let mid = (lat_interval.0 + lat_interval.1) / 2.0;
if lat > mid {
z_coordinate.push(1);
lat_interval.0 = mid;
} else {
z_coordinate.push(0);
lat_interval.1 = mid;
}
}
z_coordinate.chunks(5)
.take(precision)
.map(|chunk| {
let mut value = 0;
for (i, &bit) in chunk.iter().enumerate() {
value |= (bit as usize) << (4 - i);
}
BASE32[value]
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode_basic() {
assert_eq!(encode(57.64911, 10.40744, 8), "u4pruydq");
}
#[test]
fn test_encode_low_precision() {
assert_eq!(encode(57.64911, 10.40744, 4), "u4pr");
}
#[test]
fn test_encode_high_precision() {
assert_eq!(encode(57.64911, 10.40744, 12), "u4pruydqqvj8");
}
#[test]
fn test_extremes() {
assert_eq!(encode(90.0, 180.0, 6), "zzzzzz");
assert_eq!(encode(-90.0, -180.0, 6), "000000");
}
#[test]
fn test_zero_coordinates() {
assert_eq!(encode(0.0, 0.0, 12), "7zzzzzzzzzzz");
}
#[test]
fn test_random_coordinates() {
assert_eq!(encode(34.052235, -118.243683, 12), "9q5ctr18dkxw");
}
}