1use hashbrown::HashMap;
2use hashbrown::HashSet;
3
4use crate::{LocCode, OctreeNode, Orientation, AABB};
5use rayon::prelude::*;
6
7#[cfg(feature = "serialize")]
8use serde::{de::DeserializeOwned, Deserialize, Serialize};
9
10#[cfg(feature = "serialize")]
11use flate2::Compression;
12
13#[cfg(feature = "serialize")]
14use flate2::write::{ZlibDecoder, ZlibEncoder};
15
16#[cfg(feature = "serialize")]
17use std::{io::prelude::*, path::Path};
18
19#[derive(Debug)]
20#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
21pub struct Octree<L: LocCode, D: Send + Sync> {
22 pub content: HashMap<L, OctreeNode<D>>,
23 max_depth: u32,
24}
25
26#[cfg(feature = "dot_tree")]
27impl<L, D> Octree<L, D>
28where
29 L: LocCode + Serialize + DeserializeOwned,
30 D: Send + Sync + Serialize + DeserializeOwned,
31{
32 pub fn load_from_file<P: AsRef<Path>>(path_ref: P) -> Result<Self, std::io::Error> {
35 let path = path_ref.as_ref();
36 match path.extension() {
37 Some(x) => match x.to_str() {
38 #[cfg(feature = "dot_tree")]
39 Some("tree") => {
40 let file = std::fs::File::open(path)?;
41 let contents: Vec<u8> = file.bytes().filter_map(Result::ok).collect();
42 let mut decoder = ZlibDecoder::new(Vec::new());
43 decoder.write_all(&contents)?;
44 let contents = decoder.finish()?;
45 let tree = bincode::deserialize_from::<&[u8], Self>(&contents).unwrap();
46 Ok(tree)
47 }
48 _ => Err(std::io::Error::from(std::io::ErrorKind::InvalidData)),
49 },
50 None => Err(std::io::Error::from(std::io::ErrorKind::InvalidInput)),
51 }
52 }
53
54 pub fn save_to_file<P: AsRef<Path>>(&self, path_ref: P) -> Result<(), std::io::Error> {
56 let path = path_ref.as_ref();
57 let binary = bincode::serialize(self).unwrap();
58 let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
59 encoder.write_all(&binary)?;
60 std::fs::write(path, encoder.finish()?)
61 }
62}
63
64impl<'a, L, D> Octree<L, D>
65where
66 L: LocCode,
67 D: Send + Sync,
68{
69 pub fn size(&self) -> usize {
71 self.content.len()
72 }
73}
74
75impl<'a, T, D> Octree<T, D>
76where
77 T: LocCode,
78 D: Copy + PartialEq + Send + Sync,
79{
80 pub fn new(max_depth: u32) -> Self {
82 let content = HashMap::default();
83 Self { content, max_depth }
84 }
85
86 pub fn with_capacity(max_depth: u32, size: usize) -> Self {
88 let content = HashMap::with_capacity(size);
89 Self { content, max_depth }
90 }
91
92 pub fn depth(&self) -> u32 {
93 let keys = self.content.keys();
94 keys.max().unwrap_or(&T::root()).get_level()
95 }
96
97 pub fn lookup(&self, loc_code: T) -> Option<&OctreeNode<D>> {
99 self.content.get(&loc_code)
100 }
101
102 pub fn insert(&mut self, location: T, node: OctreeNode<D>) -> T {
104 self.content.insert(location, node);
105 location
106 }
107
108 pub fn remove_node(&mut self, loc_code: T) {
109 self.content.remove(&loc_code);
110 }
111
112 pub fn merge(&mut self, aabb: AABB, data: D) {
114 let mut codes: Vec<T> = self
115 .merge_inner(aabb, data, (0.5, 0.5, 0.5), 1, T::root())
116 .into_iter()
117 .collect();
118 while !codes.is_empty() {
119 codes.sort();
120 codes.reverse();
121 codes = codes
122 .into_iter()
123 .filter_map(|code| self.assemble(code))
124 .filter(|code| *code > T::zero())
125 .collect::<HashSet<T>>()
126 .into_iter()
127 .collect();
128 }
129 }
130
131 fn assemble(&mut self, code: T) -> Option<T> {
132 let datas = (0_u8..8_u8)
133 .map(|number| (code << T::three()) | T::from(number))
134 .filter_map(|loc_code| self.lookup(loc_code))
135 .map(|node| node.data)
136 .collect::<Vec<D>>();
137 if datas.len() != 8 {
138 None
139 } else {
140 let elem = datas[0];
141 let is_same = datas
142 .into_iter()
143 .fold((true, elem), |acc, elem| (acc.0 && acc.1 == elem, acc.1))
144 .0;
145 if !is_same {
146 None
147 } else {
148 (0_u8..8_u8)
149 .map(|number| (code << T::three()) | T::from(number))
150 .for_each(|code| self.remove_node(code));
151 self.insert(code, OctreeNode::new(elem));
152 Some(code >> T::three())
153 }
154 }
155 }
156
157 pub fn transform<U: From<D> + Send + Sync>(self) -> Octree<T, U> {
160 Octree {
161 content: self
162 .content
163 .into_par_iter()
164 .map(|(loc_code, data)| (loc_code, data.transform::<U>()))
165 .collect::<HashMap<T, OctreeNode<U>>>(),
166 max_depth: self.max_depth,
167 }
168 }
169
170 pub fn transform_fn<U: Send + Sync, F: Fn(D) -> U + Sync>(self, function: F) -> Octree<T, U> {
172 Octree {
173 content: self
174 .content
175 .into_par_iter()
176 .map(|(loc_code, data)| (loc_code, data.transform_fn(&function)))
177 .collect::<HashMap<T, OctreeNode<U>>>(),
178 max_depth: self.max_depth,
179 }
180 }
181
182 pub fn transform_nodes_fn<U: Send + Sync, F: Fn(T, OctreeNode<D>) -> OctreeNode<U> + Sync>(
184 self,
185 function: F,
186 ) -> Octree<T, U> {
187 Octree {
188 content: self
189 .content
190 .into_par_iter()
191 .map(|(loc_code, data)| (loc_code, function(loc_code, data)))
192 .collect::<HashMap<T, OctreeNode<U>>>(),
193 max_depth: self.max_depth,
194 }
195 }
196
197 fn merge_inner(
201 &mut self,
202 aabb: AABB,
203 data: D,
204 center: (f64, f64, f64),
205 depth: u32,
206 loc_code: T,
207 ) -> HashSet<T> {
208 let blocks = aabb.explode(center);
209 let max_depth = self.max_depth;
210
211 let (fitting, subdivisables): (Vec<AABB>, Vec<AABB>) = blocks
212 .into_iter()
213 .partition(|aabb| aabb.fit_in(depth, max_depth));
214
215 let mut codes: Vec<T> = fitting
216 .into_iter()
217 .map(|elem| {
218 self.insert(
219 loc_code << T::three() | elem.orientation,
220 OctreeNode::new(data),
221 )
222 })
223 .map(|loc_code| loc_code >> T::three())
224 .collect();
225
226 codes.extend(if depth != self.max_depth {
227 subdivisables
228 .into_iter()
229 .map(|aabb| {
230 let new_loc_code = (loc_code << T::three()) | aabb.orientation;
231 let new_center = aabb.orientation.make_new_center(new_loc_code, center);
232 self.merge_inner(
233 aabb.with_orientation(Orientation::N),
234 data,
235 new_center,
236 depth + 1,
237 new_loc_code,
238 )
239 })
240 .flatten()
241 .collect()
242 } else {
243 Vec::<T>::default()
244 });
245
246 codes.into_iter().collect::<HashSet<T>>()
247 }
248}
249
250impl<'a, L, D> Octree<L, D>
251where
252 L: LocCode,
253 D: Send + Sync,
254{
255 #[cfg(feature = "vox")]
256 pub fn from_dotvox<U: AsRef<str>>(
257 path: U,
258 max_depth: u32,
259 optimal: crate::dot_vox::ConversionType,
260 ) -> Result<Vec<Octree<L, u32>>, &'static str> {
261 let vox = dot_vox::load(path.as_ref())?;
262 let octrees: Vec<Octree<L, u32>> = crate::dot_vox::vox_to_octrees(vox, max_depth, optimal);
263 Ok(octrees)
264 }
265}