1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
use crate::errors::{UtilesCoreError, UtilesCoreResult};
use crate::Tile;
/// Return the quadkey for a tile as a vector of u8 values (0, 1, 2, 3).
#[must_use]
pub fn xyz2quadkey_vec(x: u32, y: u32, z: u8) -> Vec<u8> {
let mut qk_arr = Vec::with_capacity(z as usize);
// let mut quadkey = String::new();
for i in (0..z).rev() {
let mut digit: u8 = 0;
let mask = 1 << i;
if (x & mask) != 0 {
digit += 1;
}
if (y & mask) != 0 {
digit += 2;
}
qk_arr.push(digit);
}
qk_arr
}
/// Return the quadkey for a tile as a string.
/// # Examples
/// ```
/// use utiles_core::xyz2quadkey;
/// let quadkey = xyz2quadkey(486, 332, 10);
/// assert_eq!(quadkey, "0313102310");
/// ```
#[must_use]
pub fn xyz2quadkey(x: u32, y: u32, z: u8) -> String {
xyz2quadkey_vec(x, y, z)
.iter()
.map(|&c| (c + b'0') as char)
.collect()
}
/// Return (x, y, z) for a quadkey as a tuple.
///
/// # Errors
///
/// Returns an error if the quadkey is invalid and cannot be converted to
/// tile xyz.
///
/// # Examples
/// ```
/// use utiles_core::quadkey2xyz;
/// let one_two_three = quadkey2xyz("123").unwrap();
/// assert_eq!(one_two_three, (5, 3, 3));
/// let xyz = quadkey2xyz("0313102310").unwrap();
/// assert_eq!(xyz, (486, 332, 10));
/// ```
pub fn quadkey2xyz(quadkey: &str) -> UtilesCoreResult<(u32, u32, u8)> {
// Version with fold:
// quadkey.chars().try_fold((0, 0, 0), |(mut x, mut y, z), c| {
// x <<= 1;
// y <<= 1;
//
// match c {
// '0' => Ok((x, y, z + 1)),
// '1' => Ok((x | 1, y, z + 1)),
// '2' => Ok((x, y | 1, z + 1)),
// '3' => Ok((x | 1, y | 1, z + 1)),
// _ => Err(UtilesError::InvalidQuadkey(c.to_string())),
// }
// })
let mut x = 0;
let mut y = 0;
let mut z = 0;
for c in quadkey.chars() {
x <<= 1;
y <<= 1;
z += 1;
match c {
'0' => {}
'1' => {
x += 1;
}
'2' => {
y += 1;
}
'3' => {
x += 1;
y += 1;
}
_ => {
return Err(UtilesCoreError::InvalidQuadkey(c.to_string()));
}
}
}
Ok((x, y, z))
}
/// Return Tile struct from quadkey string
///
/// # Errors
///
/// Returns an error if the quadkey is invalid and cannot be converted to
/// tile xyz.
///
/// # Examples
/// ```
/// use utiles_core::{Tile, quadkey2tile};
/// let tile = quadkey2tile("0313102310").unwrap();
/// assert_eq!(tile, Tile::new(486, 332, 10));
/// ```
pub fn quadkey2tile(quadkey: &str) -> UtilesCoreResult<Tile> {
let xyz = quadkey2xyz(quadkey)?;
Ok(Tile::new(xyz.0, xyz.1, xyz.2))
}
/// Return y-flipped quadkey
#[must_use]
pub fn quadkey_flipy(quadkey: &str) -> String {
let mut quadkey_flipped = String::new();
for c in quadkey.chars() {
quadkey_flipped.push(match c {
'0' => '2',
'1' => '3',
'2' => '0',
'3' => '1',
_ => return String::new(),
});
}
quadkey_flipped
}