oxihuman_morph/
bmi_body_shape_morph.rs1#![allow(dead_code)]
4
5pub struct BmiMorph {
6 pub bmi: f32,
7 pub underweight_blend: f32,
8 pub overweight_blend: f32,
9}
10
11pub fn new_bmi_morph(bmi: f32) -> BmiMorph {
12 let clamped = bmi.clamp(10.0, 60.0);
13 let underweight_blend = if clamped < 18.5 {
14 (18.5 - clamped) / 8.5
15 } else {
16 0.0
17 };
18 let overweight_blend = if clamped > 25.0 {
19 ((clamped - 25.0) / 35.0).min(1.0)
20 } else {
21 0.0
22 };
23 BmiMorph {
24 bmi: clamped,
25 underweight_blend,
26 overweight_blend,
27 }
28}
29
30pub fn bmi_category(bmi: f32) -> &'static str {
31 if bmi < 18.5 {
32 "underweight"
33 } else if bmi < 25.0 {
34 "normal"
35 } else if bmi < 30.0 {
36 "overweight"
37 } else {
38 "obese"
39 }
40}
41
42pub fn bmi_blend_weight(m: &BmiMorph) -> f32 {
43 (m.underweight_blend + m.overweight_blend).min(1.0)
44}
45
46pub fn bmi_is_healthy(m: &BmiMorph) -> bool {
47 m.bmi >= 18.5 && m.bmi <= 25.0
48}
49
50pub fn bmi_blend(a: &BmiMorph, b: &BmiMorph, t: f32) -> BmiMorph {
51 let t = t.clamp(0.0, 1.0);
52 let bmi = a.bmi + (b.bmi - a.bmi) * t;
53 new_bmi_morph(bmi)
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn test_new_bmi_morph_normal() {
62 let m = new_bmi_morph(22.0);
64 assert!((m.bmi - 22.0).abs() < 1e-5);
65 assert!((m.underweight_blend).abs() < 1e-5);
66 assert!((m.overweight_blend).abs() < 1e-5);
67 }
68
69 #[test]
70 fn test_bmi_category() {
71 assert_eq!(bmi_category(15.0), "underweight");
73 assert_eq!(bmi_category(22.0), "normal");
74 assert_eq!(bmi_category(27.0), "overweight");
75 assert_eq!(bmi_category(35.0), "obese");
76 }
77
78 #[test]
79 fn test_bmi_blend_weight_normal() {
80 let m = new_bmi_morph(22.0);
82 assert!((bmi_blend_weight(&m)).abs() < 1e-5);
83 }
84
85 #[test]
86 fn test_bmi_is_healthy() {
87 let m_healthy = new_bmi_morph(22.0);
89 let m_under = new_bmi_morph(16.0);
90 assert!(bmi_is_healthy(&m_healthy));
91 assert!(!bmi_is_healthy(&m_under));
92 }
93
94 #[test]
95 fn test_bmi_blend() {
96 let a = new_bmi_morph(18.0);
98 let b = new_bmi_morph(30.0);
99 let c = bmi_blend(&a, &b, 0.5);
100 assert!((c.bmi - 24.0).abs() < 1e-4);
101 }
102
103 #[test]
104 fn test_bmi_category_obese() {
105 assert_eq!(bmi_category(30.0), "obese");
107 }
108}