oxihuman_morph/
pigeon_toe_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct PigeonToeMorphConfig {
10 pub intoeing_angle: f32,
11 pub femoral_anteversion: f32,
12 pub metatarsus_adductus: f32,
13}
14
15impl Default for PigeonToeMorphConfig {
16 fn default() -> Self {
17 Self {
18 intoeing_angle: 0.0,
19 femoral_anteversion: 0.0,
20 metatarsus_adductus: 0.0,
21 }
22 }
23}
24
25#[derive(Debug, Clone)]
27pub struct PigeonToeMorph {
28 pub config: PigeonToeMorphConfig,
29 pub intensity: f32,
30 pub enabled: bool,
31}
32
33impl PigeonToeMorph {
34 pub fn new() -> Self {
35 Self {
36 config: PigeonToeMorphConfig::default(),
37 intensity: 0.0,
38 enabled: true,
39 }
40 }
41}
42
43impl Default for PigeonToeMorph {
44 fn default() -> Self {
45 Self::new()
46 }
47}
48
49pub fn new_pigeon_toe_morph() -> PigeonToeMorph {
51 PigeonToeMorph::new()
52}
53
54pub fn pigeon_toe_set_intoeing(morph: &mut PigeonToeMorph, v: f32) {
56 morph.config.intoeing_angle = v.clamp(0.0, 1.0);
57}
58
59pub fn pigeon_toe_set_femoral(morph: &mut PigeonToeMorph, v: f32) {
61 morph.config.femoral_anteversion = v.clamp(0.0, 1.0);
62}
63
64pub fn pigeon_toe_set_metatarsus(morph: &mut PigeonToeMorph, v: f32) {
66 morph.config.metatarsus_adductus = v.clamp(0.0, 1.0);
67}
68
69pub fn pigeon_toe_total_rotation(morph: &PigeonToeMorph) -> f32 {
71 morph.intensity
72 * (morph.config.intoeing_angle
73 + morph.config.femoral_anteversion * 0.5
74 + morph.config.metatarsus_adductus * 0.3)
75}
76
77pub fn pigeon_toe_to_json(morph: &PigeonToeMorph) -> String {
79 format!(
80 r#"{{"intensity":{},"intoeing_angle":{},"femoral_anteversion":{},"metatarsus_adductus":{}}}"#,
81 morph.intensity,
82 morph.config.intoeing_angle,
83 morph.config.femoral_anteversion,
84 morph.config.metatarsus_adductus,
85 )
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_new() {
94 let m = new_pigeon_toe_morph();
95 assert!((m.config.intoeing_angle - 0.0).abs() < 1e-6 );
96 }
97
98 #[test]
99 fn test_intoeing_clamp() {
100 let mut m = new_pigeon_toe_morph();
101 pigeon_toe_set_intoeing(&mut m, 5.0);
102 assert!((m.config.intoeing_angle - 1.0).abs() < 1e-6 );
103 }
104
105 #[test]
106 fn test_femoral() {
107 let mut m = new_pigeon_toe_morph();
108 pigeon_toe_set_femoral(&mut m, 0.4);
109 assert!((m.config.femoral_anteversion - 0.4).abs() < 1e-6 );
110 }
111
112 #[test]
113 fn test_metatarsus() {
114 let mut m = new_pigeon_toe_morph();
115 pigeon_toe_set_metatarsus(&mut m, 0.2);
116 assert!((m.config.metatarsus_adductus - 0.2).abs() < 1e-6 );
117 }
118
119 #[test]
120 fn test_total_rotation_zero() {
121 let m = new_pigeon_toe_morph();
122 assert!((pigeon_toe_total_rotation(&m) - 0.0).abs() < 1e-6 );
123 }
124
125 #[test]
126 fn test_total_rotation_nonzero() {
127 let mut m = new_pigeon_toe_morph();
128 pigeon_toe_set_intoeing(&mut m, 1.0);
129 m.intensity = 1.0;
130 assert!(pigeon_toe_total_rotation(&m) > 0.0 );
131 }
132
133 #[test]
134 fn test_json_key() {
135 let m = new_pigeon_toe_morph();
136 let j = pigeon_toe_to_json(&m);
137 assert!(j.contains("intoeing_angle") );
138 }
139
140 #[test]
141 fn test_default_enabled() {
142 let m = PigeonToeMorph::default();
143 assert!(m.enabled );
144 }
145
146 #[test]
147 fn test_clone() {
148 let m = new_pigeon_toe_morph();
149 let c = m.clone();
150 assert!((c.intensity - m.intensity).abs() < 1e-6 );
151 }
152}