use std::collections::HashSet;
use crate::core::cell_info::get_num_children;
use crate::core::serialization::{
cell_to_children, cell_to_parent, get_resolution, get_stride, is_first_child,
FIRST_HILBERT_RESOLUTION,
};
pub fn uncompact(cells: &[u64], target_resolution: i32) -> Result<Vec<u64>, String> {
let mut n = 0;
let mut resolutions = Vec::with_capacity(cells.len());
for &cell in cells {
let resolution = get_resolution(cell);
let resolution_diff = target_resolution - resolution;
if resolution_diff < 0 {
return Err(format!(
"Cannot uncompact cell at resolution {} to lower resolution {}",
resolution, target_resolution
));
}
resolutions.push(resolution);
n += get_num_children(resolution, target_resolution);
}
let mut result = Vec::with_capacity(n);
for (i, &cell) in cells.iter().enumerate() {
let resolution = resolutions[i];
let num_children = get_num_children(resolution, target_resolution);
if num_children == 1 {
result.push(cell);
} else {
let children = cell_to_children(cell, Some(target_resolution))?;
result.extend(children);
}
}
Ok(result)
}
pub fn compact(cells: &[u64]) -> Result<Vec<u64>, String> {
if cells.is_empty() {
return Ok(Vec::new());
}
let unique_cells: HashSet<u64> = cells.iter().copied().collect();
let mut current_cells: Vec<u64> = unique_cells.into_iter().collect();
current_cells.sort_unstable();
let mut changed = true;
while changed {
changed = false;
let mut result = Vec::new();
let mut i = 0;
while i < current_cells.len() {
let cell = current_cells[i];
let resolution = get_resolution(cell);
if resolution < 0 {
result.push(cell);
i += 1;
continue;
}
let expected_children = if resolution >= FIRST_HILBERT_RESOLUTION {
4 } else if resolution == 0 {
12 } else {
5
};
if i + expected_children <= current_cells.len() {
let mut has_all_siblings = true;
if is_first_child(cell, Some(resolution)) {
let stride = get_stride(resolution);
for j in 1..expected_children {
let expected_cell = cell + (j as u64) * stride;
if current_cells[i + j] != expected_cell {
has_all_siblings = false;
break;
}
}
} else {
has_all_siblings = false;
}
if has_all_siblings {
let parent = cell_to_parent(cell, None)?;
result.push(parent);
i += expected_children;
changed = true;
continue;
}
}
result.push(cell);
i += 1;
}
current_cells = result;
}
Ok(current_cells)
}