kasane_logic/spatial_id/flex_id/
ops.rs1use crate::{FlexId, Side, SpatialId};
2
3impl FlexId {
4 pub fn difference(&self, other: &FlexId) -> impl Iterator<Item = FlexId> {
7 let mut results = Vec::new();
8
9 let intersect = match self.intersection(other) {
10 Some(i) => i,
11 None => {
12 results.push(self.clone());
13 return results.into_iter();
14 }
15 };
16
17 if self == &intersect {
18 return results.into_iter();
19 }
20
21 let mut current = self.clone();
22
23 while current.f_zoomlevel < intersect.f_zoomlevel {
24 let lower = current.f_split(Side::Lower).unwrap();
25 let upper = current.f_split(Side::Upper).unwrap();
26 if lower.intersection(&intersect).is_some() {
27 results.push(upper);
28 current = lower;
29 } else {
30 results.push(lower);
31 current = upper;
32 }
33 }
34
35 while current.x_zoomlevel < intersect.x_zoomlevel {
37 let lower = current.x_split(Side::Lower).unwrap();
38 let upper = current.x_split(Side::Upper).unwrap();
39
40 if lower.intersection(&intersect).is_some() {
41 results.push(upper);
42 current = lower;
43 } else {
44 results.push(lower);
45 current = upper;
46 }
47 }
48
49 while current.y_zoomlevel < intersect.y_zoomlevel {
51 let lower = current.y_split(Side::Lower).unwrap();
52 let upper = current.y_split(Side::Upper).unwrap();
53
54 if lower.intersection(&intersect).is_some() {
55 results.push(upper);
56 current = lower;
57 } else {
58 results.push(lower);
59 current = upper;
60 }
61 }
62
63 for t_diff in current.temporal().difference(other.temporal()) {
64 results.push(FlexId {
65 f_zoomlevel: current.f_zoomlevel,
66 f_index: current.f_index,
67 x_zoomlevel: current.x_zoomlevel,
68 x_index: current.x_index,
69 y_zoomlevel: current.y_zoomlevel,
70 y_index: current.y_index,
71 temporal_id: t_diff,
72 });
73 }
74
75 results.into_iter()
76 }
77
78 pub fn intersection(&self, other: &FlexId) -> Option<FlexId> {
81 let (f_z, f_i) = Self::intersect_axis_i32(
82 self.f_zoomlevel,
83 self.f_index,
84 other.f_zoomlevel,
85 other.f_index,
86 )?;
87
88 let (x_z, x_i) = Self::intersect_axis_u32(
89 self.x_zoomlevel,
90 self.x_index,
91 other.x_zoomlevel,
92 other.x_index,
93 )?;
94
95 let (y_z, y_i) = Self::intersect_axis_u32(
96 self.y_zoomlevel,
97 self.y_index,
98 other.y_zoomlevel,
99 other.y_index,
100 )?;
101
102 let temporal_id = self.temporal().intersection(other.temporal())?;
103
104 Some(FlexId {
105 f_zoomlevel: f_z,
106 f_index: f_i,
107 x_zoomlevel: x_z,
108 x_index: x_i,
109 y_zoomlevel: y_z,
110 y_index: y_i,
111 temporal_id,
112 })
113 }
114
115 fn intersect_axis_i32(z1: u8, i1: i32, z2: u8, i2: i32) -> Option<(u8, i32)> {
116 let (deep_z, deep_i, shallow_z, shallow_i) = if z1 > z2 {
117 (z1, i1, z2, i2)
118 } else {
119 (z2, i2, z1, i1)
120 };
121
122 let shift = deep_z - shallow_z;
123
124 if (deep_i >> shift) == shallow_i {
125 Some((deep_z, deep_i))
126 } else {
127 None
128 }
129 }
130
131 fn intersect_axis_u32(z1: u8, i1: u32, z2: u8, i2: u32) -> Option<(u8, u32)> {
132 let (deep_z, deep_i, shallow_z, shallow_i) = if z1 > z2 {
133 (z1, i1, z2, i2)
134 } else {
135 (z2, i2, z1, i1)
136 };
137
138 let shift = deep_z - shallow_z;
139 if (deep_i >> shift) == shallow_i {
140 Some((deep_z, deep_i))
141 } else {
142 None
143 }
144 }
145}