generic_octree/
loc_code.rs

1use std::{
2    fmt::Debug,
3    hash::Hash,
4    ops::{BitOr, Shl, Shr},
5};
6
7use crate::Orientation;
8
9pub trait LocCode:
10    Copy
11    + Clone
12    + Ord
13    + PartialOrd
14    + Eq
15    + PartialEq
16    + Debug
17    + Hash
18    + Send
19    + Sync
20    + Shl<Output = Self>
21    + Shr<Output = Self>
22    + BitOr<Output = Self>
23    + From<u8>
24    + BitOr<Orientation, Output = Self>
25{
26    /// Useful for many puproses
27    fn zero() -> Self;
28
29    /// Useful to get root node
30    fn root() -> Self;
31
32    /// Useful for binary trees
33    fn one() -> Self;
34
35    /// Useful for quad-trees
36    fn two() -> Self;
37
38    // Useful for oct-trees
39    fn three() -> Self;
40
41    fn get_level(self) -> u32;
42    fn get_offset(self) -> u32;
43
44    fn get_center_u32(self) -> (u32, u32, u32);
45}
46
47macro_rules! impl_loc_code_num {
48    ($ty:ident) => {
49        impl BitOr<Orientation> for $ty {
50            type Output = Self;
51
52            fn bitor(self, rhs: Orientation) -> Self {
53                match rhs {
54                    Orientation::LBU => self | 0,
55                    Orientation::LFU => self | 1,
56                    Orientation::LFD => self | 2,
57                    Orientation::LBD => self | 3,
58                    Orientation::RBD => self | 4,
59                    Orientation::RFD => self | 5,
60                    Orientation::RFU => self | 6,
61                    Orientation::RBU => self | 7,
62                    _ => self | 8,
63                }
64            }
65        }
66
67        impl LocCode for $ty {
68            fn root() -> Self {
69                Self::one()
70            }
71
72            fn one() -> Self {
73                1 as Self
74            }
75
76            fn zero() -> Self {
77                1 as Self
78            }
79
80            fn two() -> Self {
81                2 as Self
82            }
83
84            fn three() -> Self {
85                3 as Self
86            }
87
88            fn get_level(mut self) -> u32 {
89                let mut level = 1;
90                while self != 1 {
91                    self >>= 3;
92                    level += 1;
93                }
94                level as u32
95            }
96
97            fn get_offset(self) -> u32 {
98                2u32.pow(32 - self.get_level())
99            }
100
101            fn get_center_u32(self) -> (u32, u32, u32) {
102                if self == 1 {
103                    return (i32::MAX as u32, i32::MAX as u32, i32::MAX as u32);
104                }
105                let offset = 2u32.pow(32 - self.get_level());
106                let mask = Self::MAX ^ 7;
107                let center = (self >> 3).get_center_u32();
108                match (self ^ mask) & !mask {
109                    0 => (center.0 - offset, center.1 + offset, center.2 - offset),
110                    1 => (center.0 - offset, center.1 + offset, center.2 + offset),
111                    2 => (center.0 - offset, center.1 - offset, center.2 + offset),
112                    3 => (center.0 - offset, center.1 - offset, center.2 - offset),
113                    4 => (center.0 + offset, center.1 - offset, center.2 - offset),
114                    5 => (center.0 + offset, center.1 - offset, center.2 + offset),
115                    6 => (center.0 + offset, center.1 + offset, center.2 + offset),
116                    7 => (center.0 + offset, center.1 + offset, center.2 - offset),
117                    _ => (i32::MAX as u32, i32::MAX as u32, i32::MAX as u32),
118                }
119            }
120        }
121    };
122}
123
124impl_loc_code_num!(u8);
125impl_loc_code_num!(i16);
126impl_loc_code_num!(u16);
127impl_loc_code_num!(i32);
128impl_loc_code_num!(u32);
129impl_loc_code_num!(i64);
130impl_loc_code_num!(u64);