#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq)]
pub struct SkullShape {
pub cranial_width: f32,
pub cranial_depth: f32,
pub cranial_height: f32,
pub temporal_width: f32,
}
#[allow(dead_code)]
pub fn default_skull_shape() -> SkullShape {
SkullShape {
cranial_width: 0.5,
cranial_depth: 0.5,
cranial_height: 0.5,
temporal_width: 0.5,
}
}
#[allow(dead_code)]
pub fn apply_skull_shape(weights: &mut [f32], s: &SkullShape) {
if !weights.is_empty() { weights[0] = s.cranial_width; }
if weights.len() > 1 { weights[1] = s.cranial_depth; }
if weights.len() > 2 { weights[2] = s.cranial_height; }
if weights.len() > 3 { weights[3] = s.temporal_width; }
}
#[allow(dead_code)]
pub fn skull_shape_blend(a: &SkullShape, b: &SkullShape, t: f32) -> SkullShape {
let t = t.clamp(0.0, 1.0);
SkullShape {
cranial_width: a.cranial_width + (b.cranial_width - a.cranial_width) * t,
cranial_depth: a.cranial_depth + (b.cranial_depth - a.cranial_depth) * t,
cranial_height: a.cranial_height + (b.cranial_height - a.cranial_height) * t,
temporal_width: a.temporal_width + (b.temporal_width - a.temporal_width) * t,
}
}
#[allow(dead_code)]
pub fn skull_volume_estimate(s: &SkullShape) -> f32 {
let scale = |v: f32| 7.0 + v * 3.0_f32;
let a = scale(s.cranial_width);
let b = scale(s.cranial_depth);
let c = scale(s.cranial_height);
(4.0 / 3.0) * std::f32::consts::PI * a * b * c
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_values_are_half() {
let s = default_skull_shape();
assert_eq!(s.cranial_width, 0.5);
assert_eq!(s.cranial_depth, 0.5);
assert_eq!(s.cranial_height, 0.5);
assert_eq!(s.temporal_width, 0.5);
}
#[test]
fn apply_writes_four_weights() {
let s = SkullShape {
cranial_width: 0.2,
cranial_depth: 0.4,
cranial_height: 0.6,
temporal_width: 0.8,
};
let mut w = [0.0_f32; 4];
apply_skull_shape(&mut w, &s);
assert_eq!(w[0], 0.2);
assert_eq!(w[1], 0.4);
assert_eq!(w[2], 0.6);
assert_eq!(w[3], 0.8);
}
#[test]
fn apply_handles_short_slice() {
let s = default_skull_shape();
let mut w = [0.0_f32; 2];
apply_skull_shape(&mut w, &s);
assert_eq!(w[0], 0.5);
assert_eq!(w[1], 0.5);
}
#[test]
fn blend_at_zero_returns_a() {
let a = default_skull_shape();
let b = SkullShape { cranial_width: 1.0, cranial_depth: 1.0, cranial_height: 1.0, temporal_width: 1.0 };
let c = skull_shape_blend(&a, &b, 0.0);
assert_eq!(c, a);
}
#[test]
fn blend_at_one_returns_b() {
let a = default_skull_shape();
let b = SkullShape { cranial_width: 1.0, cranial_depth: 1.0, cranial_height: 1.0, temporal_width: 1.0 };
let c = skull_shape_blend(&a, &b, 1.0);
assert_eq!(c, b);
}
#[test]
fn blend_midpoint() {
let a = SkullShape { cranial_width: 0.0, cranial_depth: 0.0, cranial_height: 0.0, temporal_width: 0.0 };
let b = SkullShape { cranial_width: 1.0, cranial_depth: 1.0, cranial_height: 1.0, temporal_width: 1.0 };
let c = skull_shape_blend(&a, &b, 0.5);
assert!((c.cranial_width - 0.5).abs() < 1e-6);
}
#[test]
fn blend_clamps_t_below_zero() {
let a = default_skull_shape();
let b = SkullShape { cranial_width: 1.0, cranial_depth: 1.0, cranial_height: 1.0, temporal_width: 1.0 };
let c = skull_shape_blend(&a, &b, -1.0);
assert_eq!(c, a);
}
#[test]
fn blend_clamps_t_above_one() {
let a = default_skull_shape();
let b = SkullShape { cranial_width: 1.0, cranial_depth: 1.0, cranial_height: 1.0, temporal_width: 1.0 };
let c = skull_shape_blend(&a, &b, 2.0);
assert_eq!(c, b);
}
#[test]
fn volume_estimate_positive() {
let s = default_skull_shape();
assert!(skull_volume_estimate(&s) > 0.0);
}
#[test]
fn volume_increases_with_size() {
let small = SkullShape { cranial_width: 0.0, cranial_depth: 0.0, cranial_height: 0.0, temporal_width: 0.0 };
let large = SkullShape { cranial_width: 1.0, cranial_depth: 1.0, cranial_height: 1.0, temporal_width: 1.0 };
assert!(skull_volume_estimate(&large) > skull_volume_estimate(&small));
}
#[test]
fn apply_empty_slice_no_panic() {
let s = default_skull_shape();
let mut w: [f32; 0] = [];
apply_skull_shape(&mut w, &s);
}
}