1use crate::int_2_offset_zoom;
2
3#[must_use]
5pub fn xyz2pmid(x: u32, y: u32, z: u8) -> u64 {
6 if z == 0 {
7 return 0;
8 }
9 let base_id: u64 = (4u64.pow(u32::from(z)) - 1) / 3;
10 let h = fast_hilbert::xy2h(x, y, z);
11 base_id + h
12}
13
14#[allow(dead_code)]
16#[must_use]
17pub fn zxy2pmid(z: u8, x: u32, y: u32) -> u64 {
18 xyz2pmid(x, y, z)
19}
20
21#[must_use]
23pub fn pmid2xyz(i: u64) -> (u32, u32, u8) {
24 if i == 0 {
25 return (0, 0, 0);
26 }
27 let (i_o, z) = int_2_offset_zoom(i);
28 let (x, y) = fast_hilbert::h2xy(i_o, z);
29 (x, y, z)
30}
31
32#[allow(dead_code)]
34#[must_use]
35pub fn pmid2zxy(i: u64) -> (u8, u32, u32) {
36 let (x, y, z) = pmid2xyz(i);
37 (z, x, y)
38}
39
40#[must_use]
42pub fn parent_id(i: u64) -> u64 {
43 let mut acc: u64 = 0;
44 let mut last_acc: u64 = 0;
45 let mut z: u8 = 0;
46 loop {
47 let num_tiles: u64 = (1 << z) * (1 << z);
48 if acc + num_tiles > i {
49 return last_acc + (i - acc) / 4;
50 }
51 last_acc = acc;
52 acc += num_tiles;
53 z += 1;
54 }
55}
56
57#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn test_zxy_to_id() {
64 assert_eq!(0, zxy2pmid(0, 0, 0));
65 assert_eq!(1, zxy2pmid(1, 0, 0));
66 assert_eq!(2, zxy2pmid(1, 0, 1));
67 assert_eq!(3, zxy2pmid(1, 1, 1));
68 assert_eq!(4, zxy2pmid(1, 1, 0));
69 assert_eq!(5, zxy2pmid(2, 0, 0));
70 }
71
72 #[test]
73 fn test_id_to_zxy() {
74 let (z, x, y) = pmid2zxy(0);
75 assert_eq!(0, z);
76 assert_eq!(0, x);
77 assert_eq!(0, y);
78 let (z, x, y) = pmid2zxy(1);
79 assert_eq!(1, z);
80 assert_eq!(0, x);
81 assert_eq!(0, y);
82 let (z, x, y) = pmid2zxy(19_078_479);
83 assert_eq!(12, z);
84 assert_eq!(3423, x);
85 assert_eq!(1763, y);
86 }
87
88 #[test]
89 fn test_many_tile_ids() {
90 for z in 0..10 {
91 for x in 0..(1 << z) {
92 for y in 0..(1 << z) {
93 let id = zxy2pmid(z, x, y);
94 let (rz, rx, ry) = pmid2zxy(id);
95 assert_eq!(z, rz);
96 assert_eq!(x, rx);
97 assert_eq!(y, ry);
98 }
99 }
100 }
101 }
102
103 #[test]
104 fn test_extremes() {
105 for tz in 0..32 {
106 let dim = (1 << tz) - 1;
107 let (z, x, y) = pmid2zxy(zxy2pmid(tz, 0, 0));
108 assert_eq!(tz, z);
109 assert_eq!(0, x);
110 assert_eq!(0, y);
111 let (z, x, y) = pmid2zxy(zxy2pmid(z, dim, 0));
112 assert_eq!(tz, z);
113 assert_eq!(dim, x);
114 assert_eq!(0, y);
115 let (z, x, y) = pmid2zxy(zxy2pmid(z, 0, dim));
116 assert_eq!(tz, z);
117 assert_eq!(0, x);
118 assert_eq!(dim, y);
119 let (z, x, y) = pmid2zxy(zxy2pmid(z, dim, dim));
120 assert_eq!(tz, z);
121 assert_eq!(dim, x);
122 assert_eq!(dim, y);
123 }
124 }
125
126 #[test]
127 fn test_parent() {
128 assert_eq!(zxy2pmid(0, 0, 0), parent_id(zxy2pmid(1, 0, 0)));
129
130 assert_eq!(zxy2pmid(1, 0, 0), parent_id(zxy2pmid(2, 0, 0)));
131 assert_eq!(zxy2pmid(1, 0, 0), parent_id(zxy2pmid(2, 0, 1)));
132 assert_eq!(zxy2pmid(1, 0, 0), parent_id(zxy2pmid(2, 1, 0)));
133 assert_eq!(zxy2pmid(1, 0, 0), parent_id(zxy2pmid(2, 1, 1)));
134
135 assert_eq!(zxy2pmid(1, 0, 1), parent_id(zxy2pmid(2, 0, 2)));
136 assert_eq!(zxy2pmid(1, 0, 1), parent_id(zxy2pmid(2, 0, 3)));
137 assert_eq!(zxy2pmid(1, 0, 1), parent_id(zxy2pmid(2, 1, 2)));
138 assert_eq!(zxy2pmid(1, 0, 1), parent_id(zxy2pmid(2, 1, 3)));
139
140 assert_eq!(zxy2pmid(1, 1, 0), parent_id(zxy2pmid(2, 2, 0)));
141 assert_eq!(zxy2pmid(1, 1, 0), parent_id(zxy2pmid(2, 2, 1)));
142 assert_eq!(zxy2pmid(1, 1, 0), parent_id(zxy2pmid(2, 3, 0)));
143 assert_eq!(zxy2pmid(1, 1, 0), parent_id(zxy2pmid(2, 3, 1)));
144
145 assert_eq!(zxy2pmid(1, 1, 1), parent_id(zxy2pmid(2, 2, 2)));
146 assert_eq!(zxy2pmid(1, 1, 1), parent_id(zxy2pmid(2, 2, 3)));
147 assert_eq!(zxy2pmid(1, 1, 1), parent_id(zxy2pmid(2, 3, 2)));
148 assert_eq!(zxy2pmid(1, 1, 1), parent_id(zxy2pmid(2, 3, 3)));
149 }
150}