ovtile/
util.rs

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