1use serde::{Deserialize, Serialize};
2
3#[inline]
10fn spread_bits(x: u32) -> u64 {
11 let mut x = x as u64;
12 x = (x | (x << 16)) & 0x0000_FFFF_0000_FFFF;
13 x = (x | (x << 8)) & 0x00FF_00FF_00FF_00FF;
14 x = (x | (x << 4)) & 0x0F0F_0F0F_0F0F_0F0F;
15 x = (x | (x << 2)) & 0x3333_3333_3333_3333;
16 x = (x | (x << 1)) & 0x5555_5555_5555_5555;
17 x
18}
19
20#[inline]
23fn compact_bits(mut x: u64) -> u32 {
24 x &= 0x5555_5555_5555_5555;
25 x = (x | (x >> 1)) & 0x3333_3333_3333_3333;
26 x = (x | (x >> 2)) & 0x0F0F_0F0F_0F0F_0F0F;
27 x = (x | (x >> 4)) & 0x00FF_00FF_00FF_00FF;
28 x = (x | (x >> 8)) & 0x0000_FFFF_0000_FFFF;
29 x = (x | (x >> 16)) & 0x0000_0000_FFFF_FFFF;
30 x as u32
31}
32
33#[inline]
36pub fn morton_encode(x: u32, y: u32) -> u64 {
37 spread_bits(x) | (spread_bits(y) << 1)
38}
39
40#[inline]
42pub fn morton_decode(key: u64) -> (u32, u32) {
43 (compact_bits(key), compact_bits(key >> 1))
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
52pub struct SpcKey(u64);
53
54impl SpcKey {
55 #[inline]
57 pub fn from_raw(raw: u64) -> Self {
58 Self(raw)
59 }
60
61 #[inline]
63 pub fn from_xy(x: u32, y: u32) -> Self {
64 Self(morton_encode(x, y))
65 }
66
67 #[inline]
69 pub fn to_xy(self) -> (u32, u32) {
70 morton_decode(self.0)
71 }
72
73 #[inline]
75 pub fn raw(self) -> u64 {
76 self.0
77 }
78}
79
80impl std::fmt::Display for SpcKey {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 let (x, y) = self.to_xy();
83 write!(f, "SpcKey({}, {})", x, y)
84 }
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
93pub struct SpcRegion {
94 pub min_x: u32,
95 pub min_y: u32,
96 pub max_x: u32,
97 pub max_y: u32,
98}
99
100impl SpcRegion {
101 pub fn new(min_x: u32, min_y: u32, max_x: u32, max_y: u32) -> Self {
103 debug_assert!(min_x <= max_x, "min_x must be <= max_x");
104 debug_assert!(min_y <= max_y, "min_y must be <= max_y");
105 Self { min_x, min_y, max_x, max_y }
106 }
107
108 pub fn contains_key(&self, key: SpcKey) -> bool {
110 let (x, y) = key.to_xy();
111 x >= self.min_x && x <= self.max_x && y >= self.min_y && y <= self.max_y
112 }
113
114 pub fn key_range(&self) -> (SpcKey, SpcKey) {
119 (
120 SpcKey::from_xy(self.min_x, self.min_y),
121 SpcKey::from_xy(self.max_x, self.max_y),
122 )
123 }
124}
125
126#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn morton_round_trip() {
136 for (x, y) in [(0, 0), (1, 0), (0, 1), (255, 255), (u32::MAX, u32::MAX)] {
137 assert_eq!(morton_decode(morton_encode(x, y)), (x, y));
138 }
139 }
140
141 #[test]
142 fn spc_key_round_trip() {
143 let key = SpcKey::from_xy(42, 99);
144 assert_eq!(key.to_xy(), (42, 99));
145 }
146
147 #[test]
148 fn spc_region_contains() {
149 let region = SpcRegion::new(0, 0, 10, 10);
150 assert!(region.contains_key(SpcKey::from_xy(5, 5)));
151 assert!(region.contains_key(SpcKey::from_xy(0, 0)));
152 assert!(region.contains_key(SpcKey::from_xy(10, 10)));
153 assert!(!region.contains_key(SpcKey::from_xy(11, 5)));
154 assert!(!region.contains_key(SpcKey::from_xy(5, 11)));
155 }
156
157 #[test]
158 fn spc_region_key_range_corners() {
159 let region = SpcRegion::new(1, 2, 3, 4);
160 let (lo, hi) = region.key_range();
161 assert_eq!(lo.to_xy(), (1, 2));
162 assert_eq!(hi.to_xy(), (3, 4));
163 }
164}