#![allow(dead_code)]
#[derive(Debug, Default, Clone)]
pub struct PoseSnapshot {
pub label: String,
pub positions: Vec<[f32; 3]>,
pub normals: Option<Vec<[f32; 3]>>,
pub timestamp: f64,
}
impl PoseSnapshot {
pub fn new(label: impl Into<String>, positions: Vec<[f32; 3]>, timestamp: f64) -> Self {
Self {
label: label.into(),
positions,
normals: None,
timestamp,
}
}
pub fn with_normals(mut self, normals: Vec<[f32; 3]>) -> Self {
self.normals = Some(normals);
self
}
pub fn vertex_count(&self) -> usize {
self.positions.len()
}
pub fn has_normals(&self) -> bool {
self.normals.is_some()
}
}
#[derive(Debug, Default, Clone)]
pub struct PoseSnapshotLibrary {
pub snapshots: Vec<PoseSnapshot>,
}
impl PoseSnapshotLibrary {
pub fn new() -> Self {
Self::default()
}
pub fn add(&mut self, snapshot: PoseSnapshot) {
self.snapshots.push(snapshot);
}
pub fn find(&self, label: &str) -> Option<&PoseSnapshot> {
self.snapshots.iter().find(|s| s.label == label)
}
pub fn count(&self) -> usize {
self.snapshots.len()
}
}
pub fn snapshot_aabb(snap: &PoseSnapshot) -> ([f32; 3], [f32; 3]) {
if snap.positions.is_empty() {
return ([0.0; 3], [0.0; 3]);
}
let mut min = snap.positions[0];
let mut max = snap.positions[0];
for p in &snap.positions {
for k in 0..3 {
min[k] = min[k].min(p[k]);
max[k] = max[k].max(p[k]);
}
}
(min, max)
}
pub fn snapshot_displacement(a: &PoseSnapshot, b: &PoseSnapshot) -> f32 {
a.positions
.iter()
.zip(b.positions.iter())
.map(|(pa, pb)| {
let dx = pa[0] - pb[0];
let dy = pa[1] - pb[1];
let dz = pa[2] - pb[2];
(dx * dx + dy * dy + dz * dz).sqrt()
})
.sum()
}
pub fn scale_snapshot(snap: &mut PoseSnapshot, scale: f32) {
for p in snap.positions.iter_mut() {
p[0] *= scale;
p[1] *= scale;
p[2] *= scale;
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_snap(n: usize) -> PoseSnapshot {
PoseSnapshot::new("test", vec![[1.0, 0.0, 0.0]; n], 0.0)
}
#[test]
fn test_new_snapshot() {
assert_eq!(make_snap(5).vertex_count(), 5);
}
#[test]
fn test_has_normals_false() {
assert!(!make_snap(3).has_normals());
}
#[test]
fn test_has_normals_true() {
let snap = make_snap(2).with_normals(vec![[0.0, 1.0, 0.0]; 2]);
assert!(snap.has_normals());
}
#[test]
fn test_library_add_and_count() {
let mut lib = PoseSnapshotLibrary::new();
lib.add(make_snap(3));
assert_eq!(lib.count(), 1);
}
#[test]
fn test_library_find_existing() {
let mut lib = PoseSnapshotLibrary::new();
lib.add(make_snap(2));
assert!(lib.find("test").is_some());
}
#[test]
fn test_library_find_missing() {
let lib = PoseSnapshotLibrary::new();
assert!(lib.find("nope").is_none());
}
#[test]
fn test_snapshot_aabb_empty() {
let snap = PoseSnapshot::new("empty", vec![], 0.0);
let (min, max) = snapshot_aabb(&snap);
assert_eq!(min, [0.0; 3]);
assert_eq!(max, [0.0; 3]);
}
#[test]
fn test_snapshot_aabb_single() {
let snap = PoseSnapshot::new("s", vec![[2.0, 3.0, 4.0]], 0.0);
let (min, max) = snapshot_aabb(&snap);
assert_eq!(min, [2.0, 3.0, 4.0]);
assert_eq!(max, [2.0, 3.0, 4.0]);
}
#[test]
fn test_snapshot_displacement_same() {
let a = make_snap(3);
let b = make_snap(3);
assert!((snapshot_displacement(&a, &b)).abs() < f32::EPSILON);
}
#[test]
fn test_scale_snapshot() {
let mut snap = make_snap(2);
scale_snapshot(&mut snap, 2.0);
assert!((snap.positions[0][0] - 2.0).abs() < f32::EPSILON);
}
}