1use bitvec::{array::BitArray, order::Msb0};
2use nalgebra::{RealField, SVector, Scalar};
3use num_traits::ToPrimitive;
4
5pub struct MortonCode<T: Scalar + RealField + Copy, const N: usize> {
6 pub bits: BitArray<[u32; N], Msb0>,
7 pub position: SVector<T, N>,
8}
9
10impl<T, const N: usize> MortonCode<T, N>
11where
12 T: Scalar + RealField + Copy + ToPrimitive,
13{
14 pub fn from_vector(position: SVector<T, N>, min: &SVector<T, N>) -> Self {
15 let mut quantized = [0u32; N];
16 let mut bits = BitArray::<[u32; N], Msb0>::ZERO;
17 for i in 0..N {
18 let axis_diff = position[i] - min[i];
19
20 quantized[i] = axis_diff.to_u32().unwrap_or(0);
21 }
22 let mut current_bit = 0;
23 for bit in (0..32).rev() {
24 for q in quantized.iter().take(N) {
25 let is_set = ((q >> bit) & 1) == 1;
26 if is_set {
27 bits.set(current_bit, true);
28 }
29 current_bit += 1;
30 if current_bit >= N * 32 {
31 break;
32 }
33 }
34 }
35 Self { bits, position }
36 }
37}
38
39impl<T: Scalar + RealField + Copy> MortonCode<T, 3> {
40 pub fn to_u64(&self) -> u64 {
41 let mut out = 0u64;
42 let len = self.bits.len();
43 let take = len.min(64);
44 for i in 0..take {
45 if self.bits[len - 1 - i] {
46 out |= 1u64 << i;
47 }
48 }
49 out
50 }
51}