oxihuman_morph/
parietal_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
7pub struct ParietalMorph {
8 pub coronal_curve: f32,
10 pub sagittal_curve: f32,
12 pub boss: f32,
14}
15
16pub fn new_parietal_morph() -> ParietalMorph {
17 ParietalMorph {
18 coronal_curve: 0.0,
19 sagittal_curve: 0.0,
20 boss: 0.0,
21 }
22}
23
24pub fn par_set_coronal_curve(m: &mut ParietalMorph, v: f32) {
25 m.coronal_curve = v.clamp(0.0, 1.0);
26}
27
28pub fn par_set_sagittal_curve(m: &mut ParietalMorph, v: f32) {
29 m.sagittal_curve = v.clamp(0.0, 1.0);
30}
31
32pub fn par_set_boss(m: &mut ParietalMorph, v: f32) {
33 m.boss = v.clamp(0.0, 1.0);
34}
35
36pub fn par_overall_weight(m: &ParietalMorph) -> f32 {
37 (m.coronal_curve + m.sagittal_curve + m.boss) / 3.0
38}
39
40pub fn par_blend(a: &ParietalMorph, b: &ParietalMorph, t: f32) -> ParietalMorph {
41 let t = t.clamp(0.0, 1.0);
42 ParietalMorph {
43 coronal_curve: a.coronal_curve + (b.coronal_curve - a.coronal_curve) * t,
44 sagittal_curve: a.sagittal_curve + (b.sagittal_curve - a.sagittal_curve) * t,
45 boss: a.boss + (b.boss - a.boss) * t,
46 }
47}
48
49pub fn par_is_neutral(m: &ParietalMorph) -> bool {
50 m.coronal_curve < 1e-5 && m.sagittal_curve < 1e-5 && m.boss < 1e-5
51}
52
53pub fn par_to_json(m: &ParietalMorph) -> String {
54 format!(
55 r#"{{"coronal_curve":{:.4},"sagittal_curve":{:.4},"boss":{:.4}}}"#,
56 m.coronal_curve, m.sagittal_curve, m.boss
57 )
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn test_defaults() {
66 let m = new_parietal_morph();
68 assert_eq!(m.coronal_curve, 0.0);
69 }
70
71 #[test]
72 fn test_set_coronal() {
73 let mut m = new_parietal_morph();
75 par_set_coronal_curve(&mut m, 0.5);
76 assert!((m.coronal_curve - 0.5).abs() < 1e-6);
77 }
78
79 #[test]
80 fn test_clamp_high() {
81 let mut m = new_parietal_morph();
83 par_set_coronal_curve(&mut m, 2.0);
84 assert_eq!(m.coronal_curve, 1.0);
85 }
86
87 #[test]
88 fn test_clamp_low() {
89 let mut m = new_parietal_morph();
91 par_set_boss(&mut m, -1.0);
92 assert_eq!(m.boss, 0.0);
93 }
94
95 #[test]
96 fn test_neutral_true() {
97 assert!(par_is_neutral(&new_parietal_morph()));
99 }
100
101 #[test]
102 fn test_neutral_false() {
103 let mut m = new_parietal_morph();
105 par_set_boss(&mut m, 0.1);
106 assert!(!par_is_neutral(&m));
107 }
108
109 #[test]
110 fn test_weight() {
111 let m = ParietalMorph {
113 coronal_curve: 0.3,
114 sagittal_curve: 0.6,
115 boss: 0.9,
116 };
117 assert!((par_overall_weight(&m) - 0.6).abs() < 1e-5);
118 }
119
120 #[test]
121 fn test_blend() {
122 let a = new_parietal_morph();
124 let b = ParietalMorph {
125 coronal_curve: 1.0,
126 sagittal_curve: 0.0,
127 boss: 0.0,
128 };
129 let c = par_blend(&a, &b, 0.5);
130 assert!((c.coronal_curve - 0.5).abs() < 1e-5);
131 }
132
133 #[test]
134 fn test_to_json() {
135 assert!(par_to_json(&new_parietal_morph()).contains("coronal_curve"));
137 }
138
139 #[test]
140 fn test_clone() {
141 let m = ParietalMorph {
143 coronal_curve: 0.1,
144 sagittal_curve: 0.2,
145 boss: 0.3,
146 };
147 let m2 = m.clone();
148 assert_eq!(m.boss, m2.boss);
149 }
150}