open_vector_tile/
util.rs

1use crate::{Point, Point3D};
2use alloc::{vec, vec::Vec};
3use core::cmp::Ordering;
4use libm::round;
5use s2json::{BBOX, BBox, BBox3D};
6
7/// Manager for float based comparisons
8pub trait CustomOrd {
9    /// Custom comparison
10    fn custom_cmp(&self, other: &Self) -> Ordering;
11}
12impl CustomOrd for u64 {
13    fn custom_cmp(&self, other: &Self) -> Ordering {
14        self.partial_cmp(other).unwrap_or(Ordering::Equal)
15    }
16}
17impl CustomOrd for i64 {
18    fn custom_cmp(&self, other: &Self) -> Ordering {
19        self.partial_cmp(other).unwrap_or(Ordering::Equal)
20    }
21}
22impl CustomOrd for f32 {
23    fn custom_cmp(&self, other: &Self) -> Ordering {
24        if self.is_nan() || other.is_nan() {
25            Ordering::Equal // Or handle NaNs differently if needed
26        } else {
27            self.partial_cmp(other).unwrap_or(Ordering::Equal)
28        }
29    }
30}
31impl CustomOrd for f64 {
32    fn custom_cmp(&self, other: &Self) -> Ordering {
33        if self.is_nan() || other.is_nan() {
34            Ordering::Equal // Or handle NaNs differently if needed
35        } else {
36            self.partial_cmp(other).unwrap_or(Ordering::Equal)
37        }
38    }
39}
40/// Wrapper struct for custom ordering
41#[derive(Debug, Default, Clone, Copy)]
42pub struct CustomOrdWrapper<T>(pub T);
43impl<T: CustomOrd> CustomOrd for CustomOrdWrapper<T> {
44    fn custom_cmp(&self, other: &Self) -> Ordering {
45        self.0.custom_cmp(&other.0)
46    }
47}
48impl<T: CustomOrd> PartialOrd for CustomOrdWrapper<T> {
49    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
50        Some(self.cmp(other))
51    }
52}
53impl<T: CustomOrd> Eq for CustomOrdWrapper<T> {}
54impl<T: CustomOrd> PartialEq for CustomOrdWrapper<T> {
55    fn eq(&self, other: &Self) -> bool {
56        self.0.custom_cmp(&other.0) == Ordering::Equal
57    }
58}
59impl<T: CustomOrd> Ord for CustomOrdWrapper<T> {
60    fn cmp(&self, other: &Self) -> Ordering {
61        self.custom_cmp(other)
62    }
63}
64
65/// Encode a command with the given length of the data that follows.
66pub fn command_encode(cmd: u8, len: u32) -> u64 {
67    ((len << 3) + ((cmd as u32) & 0x7)) as u64
68}
69
70/// A command container. Decoding of a comand and length
71#[derive(Debug, PartialEq)]
72pub struct Command {
73    /// The command
74    pub cmd: u8,
75    /// The length
76    pub len: u32,
77}
78
79/// Decode a command with the given length of the data that follows.
80pub fn command_decode(cmd: u64) -> Command {
81    Command { cmd: (cmd & 0x7) as u8, len: (cmd >> 3) as u32 }
82}
83
84/// Applies zigzag encoding to transform a signed integer into an unsigned integer.
85pub fn zigzag(n: i32) -> u32 {
86    ((n << 1) ^ (n >> 31)) as u32
87}
88
89/// Applies zigzag decoding to transform an unsigned integer into a signed integer.
90pub fn zagzig(n: u32) -> i32 {
91    ((n >> 1) as i32) ^ -(n as i32 & 1)
92}
93
94/// Interweave two 16-bit numbers into a 32-bit number.
95/// In theory two small numbers can end up varint encoded to use less space.
96pub fn weave_2d(a: u16, b: u16) -> u32 {
97    let mut a = a as u32;
98    let mut b = b as u32;
99    let mut result: u32 = 0;
100    for i in 0..16 {
101        result |= (a & 1) << (i * 2); // Take ith bit from `a` and put it at position 2*i
102        result |= (b & 1) << (i * 2 + 1); // Take ith bit from `b` and put it at position 2*i+1
103        // move to next bit
104        a >>= 1;
105        b >>= 1;
106    }
107
108    result
109}
110
111/// Deweave a 32-bit number into two 16-bit numbers.
112pub fn unweave_2d(num: u32) -> (u16, u16) {
113    let mut num = num;
114    let mut a: u16 = 0;
115    let mut b: u16 = 0;
116    for i in 0..16 {
117        let bit = 1 << i;
118        if num & 1 != 0 {
119            a |= bit;
120        }
121        if num & 2 != 0 {
122            b |= bit;
123        }
124        num >>= 2;
125    }
126
127    (a, b)
128}
129
130/// Interweave three 16-bit numbers into a 48-bit number.
131/// In theory three small numbers can end up varint encoded to use less space.
132pub fn weave_3d(a: u16, b: u16, c: u16) -> u64 {
133    // return result
134    let mut result: u64 = 0;
135    let mut a: u64 = a.into();
136    let mut b: u64 = b.into();
137    let mut c: u64 = c.into();
138
139    for i in 0..16 {
140        if a & 1 != 0 {
141            result |= 1 << (i * 3);
142        } // Take ith bit from `a` and put it at position 3*i
143        if b & 1 != 0 {
144            result |= 1 << (i * 3 + 1);
145        } // Take ith bit from `b` and put it at position 3*i+1
146        if c & 1 != 0 {
147            result |= 1 << (i * 3 + 2);
148        } // Take ith bit from `c` and put it at position 3*i+2
149        // Move to the next bit
150        a >>= 1;
151        b >>= 1;
152        c >>= 1;
153    }
154
155    result
156}
157
158/// Deweave a 48-bit number into three 16-bit numbers.
159/// Returns the three 16-bit numbers in a tuple.
160pub fn unweave_3d(num: u64) -> (u32, u32, u32) {
161    let mut a = 0;
162    let mut b = 0;
163    let mut c = 0;
164    let mut num = num; // Make a mutable copy of the input
165
166    for i in 0..16 {
167        let bit = 1 << i;
168        if (num & 1) != 0 {
169            a |= bit;
170        }
171        if (num & 2) != 0 {
172            b |= bit;
173        }
174        if (num & 4) != 0 {
175            c |= bit;
176        }
177        num >>= 3; // Right shift the number by 3 positions
178    }
179
180    (a, b, c)
181}
182
183/// Encode an array of points using interweaving and delta encoding.
184pub fn weave_and_delta_encode_array(array: &[Point]) -> Vec<u64> {
185    let mut res = Vec::new();
186    let mut prev_x = 0;
187    let mut prev_y = 0;
188
189    for point in array.iter() {
190        let pos_x = zigzag(point.x - prev_x);
191        let pos_y = zigzag(point.y - prev_y);
192        res.push(weave_2d(pos_x as u16, pos_y as u16).into());
193        prev_x = point.x;
194        prev_y = point.y;
195    }
196
197    res
198}
199
200/// Decode an array of points that were encoded using interweaving and delta encoding.
201pub fn unweave_and_delta_decode_array(array: &[u64]) -> Vec<Point> {
202    let mut res = Vec::new();
203    let mut prev_x = 0;
204    let mut prev_y = 0;
205
206    for &encoded_num in array {
207        let (a, b) = unweave_2d(encoded_num as u32);
208        let x = zagzig(a as u32) + prev_x;
209        let y = zagzig(b as u32) + prev_y;
210        res.push(Point::new(x, y));
211        prev_x = x;
212        prev_y = y;
213    }
214
215    res
216}
217
218/// Encode an array of 3D points using interweaving and delta encoding.
219pub fn weave_and_delta_encode_3d_array(array: &[Point3D]) -> Vec<u64> {
220    let mut res = Vec::new();
221    let mut offset_x = 0;
222    let mut offset_y = 0;
223    let mut offset_z = 0;
224
225    for point in array.iter() {
226        let pos_x = zigzag(point.x - offset_x);
227        let pos_y = zigzag(point.y - offset_y);
228        let pos_z = zigzag(point.z - offset_z);
229        res.push(weave_3d(pos_x as u16, pos_y as u16, pos_z as u16));
230        offset_x = point.x;
231        offset_y = point.y;
232        offset_z = point.z;
233    }
234
235    res
236}
237
238/// Decode an array of 3D points that were encoded using interweaving and delta encoding.
239pub fn unweave_and_delta_decode_3d_array(array: &[u64]) -> Vec<Point3D> {
240    let mut res = Vec::new();
241    let mut offset_x = 0;
242    let mut offset_y = 0;
243    let mut offset_z = 0;
244
245    for &encoded_num in array {
246        let (a, b, c) = unweave_3d(encoded_num);
247        let x = zagzig(a) + offset_x;
248        let y = zagzig(b) + offset_y;
249        let z = zagzig(c) + offset_z;
250        res.push(Point3D::new(x, y, z));
251        offset_x = x;
252        offset_y = y;
253        offset_z = z;
254    }
255
256    res
257}
258
259/// Encode an array using delta encoding.
260pub fn delta_encode_array(array: &[u32]) -> Vec<u32> {
261    let mut res = Vec::new();
262    let mut offset = 0;
263
264    for &num in array {
265        let num = num as i32;
266        let encoded = zigzag(num - offset);
267        res.push(encoded);
268        offset = num;
269    }
270
271    res
272}
273
274/// Decode an array that was encoded using delta encoding.
275pub fn delta_decode_array(array: &[u32]) -> Vec<u32> {
276    let mut res = Vec::new();
277    let mut offset = 0;
278
279    for &encoded_num in array {
280        let num = zagzig(encoded_num) + offset;
281        res.push(num as u32);
282        offset = num;
283    }
284
285    res
286}
287
288/// Encode a sorted array using delta encoding.
289pub fn delta_encode_sorted_array(array: &[i32]) -> Vec<u32> {
290    let mut res = Vec::new();
291    let mut offset = 0;
292
293    for &num in array {
294        let delta = (num - offset) as u32; // Safe conversion as the array is sorted
295        res.push(delta);
296        offset = num;
297    }
298
299    res
300}
301
302/// Decode a sorted array that was encoded using delta encoding.
303pub fn delta_decode_sorted_array(array: &[u32]) -> Vec<i32> {
304    let mut res = Vec::new();
305    let mut offset = 0;
306
307    for &encoded_num in array {
308        let num = encoded_num as i32 + offset; // Casting to i32; since encoded as non-negative delta
309        res.push(num);
310        offset = num;
311    }
312
313    res
314}
315
316/// 24-bit quantization
317/// ~0.000021457672119140625 degrees precision
318/// ~2.388 meters precision
319pub fn quantize_lon(lon: f64) -> i32 {
320    round((lon + 180.0) * 16_777_215.0 / 360.0) as i32
321}
322
323/// 24-bit quantization
324/// ~0.000010728836059570312 degrees precision
325/// ~1.194 meters precision
326pub fn quantize_lat(lat: f64) -> i32 {
327    ((lat + 90.0) * 16_777_215.0 / 180.0) as i32
328}
329
330/// Converts quantized longitude back to geographical longitude
331pub fn dequantize_lon(q_lon: i32) -> f64 {
332    (q_lon as f64 * 360.0 / 16_777_215.0) - 180.0
333}
334
335/// Converts quantized latitude back to geographical latitude
336pub fn dequantize_lat(q_lat: i32) -> f64 {
337    (q_lat as f64 * 180.0 / 16_777_215.0) - 90.0
338}
339
340/// Packs a 24-bit integer into a buffer at the specified offset.
341pub fn pack24_bit_uint(buffer: &mut [u8], value: i32, offset: usize) {
342    buffer[offset] = ((value >> 16) & 0xff) as u8;
343    buffer[offset + 1] = ((value >> 8) & 0xff) as u8;
344    buffer[offset + 2] = (value & 0xff) as u8;
345}
346
347/// Unpacks a 24-bit integer from a buffer at the specified offset.
348pub fn unpack24_bit_uint(buffer: &[u8], offset: usize) -> i32 {
349    ((buffer[offset] as i32) << 16)
350        | ((buffer[offset + 1] as i32) << 8)
351        | (buffer[offset + 2] as i32)
352}
353
354/// Packs a float into a buffer at the specified offset using little-endian format.
355pub fn pack_float(buffer: &mut [u8], value: f32, offset: usize) {
356    let bytes: [u8; 4] = value.to_le_bytes(); // Converts the float to little-endian byte array
357    buffer[offset..offset + 4].copy_from_slice(&bytes);
358}
359
360/// Unpacks a float from a buffer at the specified offset using little-endian format.
361pub fn unpack_float(buffer: &[u8], offset: usize) -> f32 {
362    f32::from_le_bytes(buffer[offset..offset + 4].try_into().unwrap()) // Converts little-endian bytes back to a float
363}
364
365/// | Decimal Places | Approximate Accuracy in Distance       |
366/// |----------------|----------------------------------------|
367/// | 0              | 111 km (69 miles)                      |
368/// | 1              | 11.1 km (6.9 miles)                    |
369/// | 2              | 1.11 km (0.69 miles)                   |
370/// | 3              | 111 meters (364 feet)                  |
371/// | 4              | 11.1 meters (36.4 feet)                |
372/// | 5              | 1.11 meters (3.64 feet)                |
373/// | 6              | 0.111 meters (11.1 cm or 4.39 inches)  |
374/// | 7              | 1.11 cm (0.44 inches)                  |
375/// | 8              | 1.11 mm (0.044 inches)                 |
376/// 24-bit quantization for longitude and latitude
377///
378/// LONGITUDE:
379/// - ~0.000021457672119140625 degrees precision
380/// - ~2.388 meters precision
381///
382/// LATITUDE:
383/// - ~0.000010728836059570312 degrees precision
384/// - ~1.194 meters precision
385pub trait BBoxQuantization {
386    /// Returns a quantized version of the BBox
387    fn quantize(&self) -> Vec<u8>;
388    /// Dequantize the BBox
389    fn dequantize(buf: &[u8]) -> Self;
390}
391impl BBoxQuantization for BBox {
392    fn quantize(&self) -> Vec<u8> {
393        let mut buffer = vec![0u8; 12];
394
395        let q_lon1 = quantize_lon(self.left);
396        let q_lat1 = quantize_lat(self.bottom);
397        let q_lon2 = quantize_lon(self.right);
398        let q_lat2 = quantize_lat(self.top);
399
400        pack24_bit_uint(&mut buffer, q_lon1, 0);
401        pack24_bit_uint(&mut buffer, q_lat1, 3);
402        pack24_bit_uint(&mut buffer, q_lon2, 6);
403        pack24_bit_uint(&mut buffer, q_lat2, 9);
404
405        buffer
406    }
407    fn dequantize(buf: &[u8]) -> BBox {
408        let q_lon1 = unpack24_bit_uint(buf, 0);
409        let q_lat1 = unpack24_bit_uint(buf, 3);
410        let q_lon2 = unpack24_bit_uint(buf, 6);
411        let q_lat2 = unpack24_bit_uint(buf, 9);
412
413        BBox {
414            left: dequantize_lon(q_lon1),
415            bottom: dequantize_lat(q_lat1),
416            right: dequantize_lon(q_lon2),
417            top: dequantize_lat(q_lat2),
418        }
419    }
420}
421impl BBoxQuantization for BBox3D {
422    fn quantize(&self) -> Vec<u8> {
423        let mut buffer = vec![0u8; 20];
424
425        let q_lon1 = quantize_lon(self.left);
426        let q_lat1 = quantize_lat(self.bottom);
427        let q_lon2 = quantize_lon(self.right);
428        let q_lat2 = quantize_lat(self.top);
429
430        pack24_bit_uint(&mut buffer, q_lon1, 0);
431        pack24_bit_uint(&mut buffer, q_lat1, 3);
432        pack24_bit_uint(&mut buffer, q_lon2, 6);
433        pack24_bit_uint(&mut buffer, q_lat2, 9);
434
435        pack_float(&mut buffer, self.near as f32, 12);
436        pack_float(&mut buffer, self.far as f32, 16);
437
438        buffer
439    }
440    fn dequantize(buf: &[u8]) -> Self {
441        let q_lon1 = unpack24_bit_uint(buf, 0);
442        let q_lat1 = unpack24_bit_uint(buf, 3);
443        let q_lon2 = unpack24_bit_uint(buf, 6);
444        let q_lat2 = unpack24_bit_uint(buf, 9);
445
446        let near = unpack_float(buf, 12) as f64;
447        let far = unpack_float(buf, 16) as f64;
448
449        BBox3D {
450            left: dequantize_lon(q_lon1),
451            bottom: dequantize_lat(q_lat1),
452            right: dequantize_lon(q_lon2),
453            top: dequantize_lat(q_lat2),
454            near,
455            far,
456        }
457    }
458}
459
460impl BBoxQuantization for BBOX {
461    fn quantize(&self) -> Vec<u8> {
462        match self {
463            BBOX::BBox(bbox) => bbox.quantize(),
464            BBOX::BBox3D(bbox) => bbox.quantize(),
465        }
466    }
467    fn dequantize(buf: &[u8]) -> Self {
468        if buf.len() == 12 {
469            BBOX::BBox(BBox::dequantize(buf))
470        } else {
471            BBOX::BBox3D(BBox3D::dequantize(buf))
472        }
473    }
474}