#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FemurMorph {
pub length: f32,
pub neck_angle: f32,
pub anteversion: f32,
pub condyle_width: f32,
}
impl FemurMorph {
pub fn new() -> Self {
Self {
length: 0.5,
neck_angle: 0.5,
anteversion: 0.5,
condyle_width: 0.5,
}
}
}
impl Default for FemurMorph {
fn default() -> Self {
Self::new()
}
}
pub fn new_femur_morph() -> FemurMorph {
FemurMorph::new()
}
pub fn fem_set_length(m: &mut FemurMorph, v: f32) {
m.length = v.clamp(0.0, 1.0);
}
pub fn fem_set_neck_angle(m: &mut FemurMorph, v: f32) {
m.neck_angle = v.clamp(0.0, 1.0);
}
pub fn fem_set_anteversion(m: &mut FemurMorph, v: f32) {
m.anteversion = v.clamp(0.0, 1.0);
}
pub fn fem_set_condyle_width(m: &mut FemurMorph, v: f32) {
m.condyle_width = v.clamp(0.0, 1.0);
}
pub fn fem_q_angle(m: &FemurMorph) -> f32 {
(m.neck_angle * 0.6 + m.anteversion * 0.4).clamp(0.0, 1.0)
}
pub fn femur_morph_to_json(m: &FemurMorph) -> String {
format!(
r#"{{"length":{:.4},"neck_angle":{:.4},"anteversion":{:.4},"condyle_width":{:.4}}}"#,
m.length, m.neck_angle, m.anteversion, m.condyle_width
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_defaults() {
let m = new_femur_morph();
assert!((m.length - 0.5).abs() < 1e-6);
assert!((m.neck_angle - 0.5).abs() < 1e-6);
}
#[test]
fn test_length_clamp() {
let mut m = new_femur_morph();
fem_set_length(&mut m, 3.0);
assert_eq!(m.length, 1.0);
}
#[test]
fn test_neck_angle_clamp() {
let mut m = new_femur_morph();
fem_set_neck_angle(&mut m, -0.5);
assert_eq!(m.neck_angle, 0.0);
}
#[test]
fn test_anteversion_set() {
let mut m = new_femur_morph();
fem_set_anteversion(&mut m, 0.8);
assert!((m.anteversion - 0.8).abs() < 1e-6);
}
#[test]
fn test_condyle_set() {
let mut m = new_femur_morph();
fem_set_condyle_width(&mut m, 0.7);
assert!((m.condyle_width - 0.7).abs() < 1e-6);
}
#[test]
fn test_q_angle_range() {
let m = new_femur_morph();
let q = fem_q_angle(&m);
assert!((0.0..=1.0).contains(&q));
}
#[test]
fn test_q_angle_increases() {
let mut m = new_femur_morph();
let q0 = fem_q_angle(&m);
fem_set_neck_angle(&mut m, 1.0);
fem_set_anteversion(&mut m, 1.0);
let q1 = fem_q_angle(&m);
assert!(q1 > q0);
}
#[test]
fn test_json_keys() {
let m = new_femur_morph();
let s = femur_morph_to_json(&m);
assert!(s.contains("anteversion"));
}
#[test]
fn test_clone() {
let m = new_femur_morph();
let m2 = m.clone();
assert!((m2.condyle_width - m.condyle_width).abs() < 1e-6);
}
}