use std::io::{Read, Write};
use crate::io::le;
use crate::Result;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct VoxelKey {
pub level: i32,
pub x: i32,
pub y: i32,
pub z: i32,
}
impl VoxelKey {
pub const ROOT: VoxelKey = VoxelKey { level: 0, x: 0, y: 0, z: 0 };
pub fn read<R: Read>(r: &mut R) -> Result<Self> {
Ok(VoxelKey {
level: le::read_i32(r)?,
x: le::read_i32(r)?,
y: le::read_i32(r)?,
z: le::read_i32(r)?,
})
}
pub fn write<W: Write>(&self, w: &mut W) -> Result<()> {
le::write_i32(w, self.level)?;
le::write_i32(w, self.x)?;
le::write_i32(w, self.y)?;
le::write_i32(w, self.z)?;
Ok(())
}
pub fn children(self) -> [VoxelKey; 8] {
let l = self.level + 1;
let (x, y, z) = (self.x * 2, self.y * 2, self.z * 2);
[
VoxelKey { level: l, x, y, z },
VoxelKey { level: l, x:x+1, y, z },
VoxelKey { level: l, x, y:y+1, z },
VoxelKey { level: l, x:x+1, y:y+1, z },
VoxelKey { level: l, x, y, z:z+1 },
VoxelKey { level: l, x:x+1, y, z:z+1 },
VoxelKey { level: l, x, y:y+1, z:z+1 },
VoxelKey { level: l, x:x+1, y:y+1, z:z+1 },
]
}
}
#[derive(Debug, Clone, Copy)]
pub struct CopcEntry {
pub key: VoxelKey,
pub offset: u64,
pub byte_size: i32,
pub point_count: i32,
}
impl CopcEntry {
pub const SIZE: usize = 32;
pub fn read<R: Read>(r: &mut R) -> Result<Self> {
let key = VoxelKey::read(r)?;
let offset = le::read_u64(r)?;
let byte_size = le::read_i32(r)?;
let point_count = le::read_i32(r)?;
Ok(CopcEntry { key, offset, byte_size, point_count })
}
pub fn write<W: Write>(&self, w: &mut W) -> Result<()> {
self.key.write(w)?;
le::write_u64(w, self.offset)?;
le::write_i32(w, self.byte_size)?;
le::write_i32(w, self.point_count)?;
Ok(())
}
}
#[derive(Debug, Clone, Default)]
pub struct CopcHierarchy {
pub entries: Vec<CopcEntry>,
}
impl CopcHierarchy {
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
let mut cur = std::io::Cursor::new(bytes);
let count = bytes.len() / CopcEntry::SIZE;
let mut entries = Vec::with_capacity(count);
for _ in 0..count {
entries.push(CopcEntry::read(&mut cur)?);
}
Ok(CopcHierarchy { entries })
}
pub fn to_bytes(&self) -> Result<Vec<u8>> {
let mut buf = Vec::with_capacity(self.entries.len() * CopcEntry::SIZE);
for e in &self.entries { e.write(&mut buf)?; }
Ok(buf)
}
pub fn find(&self, key: VoxelKey) -> Option<&CopcEntry> {
self.entries.iter().find(|e| e.key == key)
}
}
#[derive(Debug, Clone, Default)]
pub struct CopcInfo {
pub center_x: f64,
pub center_y: f64,
pub center_z: f64,
pub halfsize: f64,
pub spacing: f64,
pub hierarchy_root_offset: u64,
pub hierarchy_root_size: u64,
pub gps_time_minimum: f64,
pub gps_time_maximum: f64,
}
impl CopcInfo {
pub const SIZE: usize = 160;
pub fn from_bytes(b: &[u8]) -> Result<Self> {
let mut cur = std::io::Cursor::new(b);
Ok(CopcInfo {
center_x: le::read_f64(&mut cur)?,
center_y: le::read_f64(&mut cur)?,
center_z: le::read_f64(&mut cur)?,
halfsize: le::read_f64(&mut cur)?,
spacing: le::read_f64(&mut cur)?,
hierarchy_root_offset: le::read_u64(&mut cur)?,
hierarchy_root_size: le::read_u64(&mut cur)?,
gps_time_minimum: le::read_f64(&mut cur)?,
gps_time_maximum: le::read_f64(&mut cur)?,
})
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(Self::SIZE);
buf.extend_from_slice(&self.center_x.to_le_bytes());
buf.extend_from_slice(&self.center_y.to_le_bytes());
buf.extend_from_slice(&self.center_z.to_le_bytes());
buf.extend_from_slice(&self.halfsize.to_le_bytes());
buf.extend_from_slice(&self.spacing.to_le_bytes());
buf.extend_from_slice(&self.hierarchy_root_offset.to_le_bytes());
buf.extend_from_slice(&self.hierarchy_root_size.to_le_bytes());
buf.extend_from_slice(&self.gps_time_minimum.to_le_bytes());
buf.extend_from_slice(&self.gps_time_maximum.to_le_bytes());
buf.resize(Self::SIZE, 0);
buf
}
}