oxihuman_morph/
humerus_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct HumerusMorph {
10 pub length: f32,
11 pub head_size: f32,
12 pub shaft_curvature: f32,
13 pub epicondyle_width: f32,
14}
15
16impl HumerusMorph {
17 pub fn new() -> Self {
18 Self {
19 length: 0.5,
20 head_size: 0.5,
21 shaft_curvature: 0.0,
22 epicondyle_width: 0.5,
23 }
24 }
25}
26
27impl Default for HumerusMorph {
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33pub fn new_humerus_morph() -> HumerusMorph {
35 HumerusMorph::new()
36}
37
38pub fn hum_set_length(m: &mut HumerusMorph, v: f32) {
40 m.length = v.clamp(0.0, 1.0);
41}
42
43pub fn hum_set_head_size(m: &mut HumerusMorph, v: f32) {
45 m.head_size = v.clamp(0.0, 1.0);
46}
47
48pub fn hum_set_shaft_curvature(m: &mut HumerusMorph, v: f32) {
50 m.shaft_curvature = v.clamp(0.0, 1.0);
51}
52
53pub fn hum_set_epicondyle_width(m: &mut HumerusMorph, v: f32) {
55 m.epicondyle_width = v.clamp(0.0, 1.0);
56}
57
58pub fn hum_elbow_breadth(m: &HumerusMorph) -> f32 {
60 m.epicondyle_width * (0.8 + m.length * 0.2)
61}
62
63pub fn humerus_morph_to_json(m: &HumerusMorph) -> String {
65 format!(
66 r#"{{"length":{:.4},"head_size":{:.4},"shaft_curvature":{:.4},"epicondyle_width":{:.4}}}"#,
67 m.length, m.head_size, m.shaft_curvature, m.epicondyle_width
68 )
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn test_defaults() {
77 let m = new_humerus_morph();
78 assert!((m.length - 0.5).abs() < 1e-6);
79 assert_eq!(m.shaft_curvature, 0.0);
80 }
81
82 #[test]
83 fn test_length_clamp() {
84 let mut m = new_humerus_morph();
85 hum_set_length(&mut m, 2.0);
86 assert_eq!(m.length, 1.0);
87 }
88
89 #[test]
90 fn test_head_size_set() {
91 let mut m = new_humerus_morph();
92 hum_set_head_size(&mut m, 0.8);
93 assert!((m.head_size - 0.8).abs() < 1e-6);
94 }
95
96 #[test]
97 fn test_curvature_clamp() {
98 let mut m = new_humerus_morph();
99 hum_set_shaft_curvature(&mut m, -1.0);
100 assert_eq!(m.shaft_curvature, 0.0);
101 }
102
103 #[test]
104 fn test_epicondyle_set() {
105 let mut m = new_humerus_morph();
106 hum_set_epicondyle_width(&mut m, 0.7);
107 assert!((m.epicondyle_width - 0.7).abs() < 1e-6);
108 }
109
110 #[test]
111 fn test_elbow_breadth_positive() {
112 let m = new_humerus_morph();
113 assert!(hum_elbow_breadth(&m) > 0.0);
114 }
115
116 #[test]
117 fn test_elbow_breadth_scales_with_epicondyle() {
118 let mut m = new_humerus_morph();
119 let b0 = hum_elbow_breadth(&m);
120 hum_set_epicondyle_width(&mut m, 1.0);
121 let b1 = hum_elbow_breadth(&m);
122 assert!(b1 > b0);
123 }
124
125 #[test]
126 fn test_json_keys() {
127 let m = new_humerus_morph();
128 let s = humerus_morph_to_json(&m);
129 assert!(s.contains("epicondyle_width"));
130 }
131
132 #[test]
133 fn test_clone() {
134 let m = new_humerus_morph();
135 let m2 = m.clone();
136 assert!((m2.head_size - m.head_size).abs() < 1e-6);
137 }
138}