oxihuman_morph/
bow_leg_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct BowLegMorphConfig {
10 pub varus_angle: f32,
11 pub tibial_torsion: f32,
12 pub ankle_inversion: f32,
13}
14
15impl Default for BowLegMorphConfig {
16 fn default() -> Self {
17 Self {
18 varus_angle: 0.0,
19 tibial_torsion: 0.0,
20 ankle_inversion: 0.0,
21 }
22 }
23}
24
25#[derive(Debug, Clone)]
27pub struct BowLegMorph {
28 pub config: BowLegMorphConfig,
29 pub intensity: f32,
30 pub symmetric: bool,
31}
32
33impl BowLegMorph {
34 pub fn new() -> Self {
35 Self {
36 config: BowLegMorphConfig::default(),
37 intensity: 0.0,
38 symmetric: true,
39 }
40 }
41}
42
43impl Default for BowLegMorph {
44 fn default() -> Self {
45 Self::new()
46 }
47}
48
49pub fn new_bow_leg_morph() -> BowLegMorph {
51 BowLegMorph::new()
52}
53
54pub fn bow_leg_set_varus(morph: &mut BowLegMorph, v: f32) {
56 morph.config.varus_angle = v.clamp(0.0, 1.0);
57}
58
59pub fn bow_leg_set_torsion(morph: &mut BowLegMorph, v: f32) {
61 morph.config.tibial_torsion = v.clamp(0.0, 1.0);
62}
63
64pub fn bow_leg_set_inversion(morph: &mut BowLegMorph, v: f32) {
66 morph.config.ankle_inversion = v.clamp(0.0, 1.0);
67}
68
69pub fn bow_leg_bow_out(morph: &BowLegMorph) -> f32 {
71 morph.intensity * morph.config.varus_angle
72}
73
74pub fn bow_leg_to_json(morph: &BowLegMorph) -> String {
76 format!(
77 r#"{{"intensity":{},"varus_angle":{},"tibial_torsion":{},"ankle_inversion":{}}}"#,
78 morph.intensity,
79 morph.config.varus_angle,
80 morph.config.tibial_torsion,
81 morph.config.ankle_inversion,
82 )
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_new() {
91 let m = new_bow_leg_morph();
92 assert!((m.config.varus_angle - 0.0).abs() < 1e-6 );
93 }
94
95 #[test]
96 fn test_varus_clamp_high() {
97 let mut m = new_bow_leg_morph();
98 bow_leg_set_varus(&mut m, 10.0);
99 assert!((m.config.varus_angle - 1.0).abs() < 1e-6 );
100 }
101
102 #[test]
103 fn test_varus_clamp_low() {
104 let mut m = new_bow_leg_morph();
105 bow_leg_set_varus(&mut m, -1.0);
106 assert!((m.config.varus_angle - 0.0).abs() < 1e-6 );
107 }
108
109 #[test]
110 fn test_torsion() {
111 let mut m = new_bow_leg_morph();
112 bow_leg_set_torsion(&mut m, 0.6);
113 assert!((m.config.tibial_torsion - 0.6).abs() < 1e-6 );
114 }
115
116 #[test]
117 fn test_inversion() {
118 let mut m = new_bow_leg_morph();
119 bow_leg_set_inversion(&mut m, 0.2);
120 assert!((m.config.ankle_inversion - 0.2).abs() < 1e-6 );
121 }
122
123 #[test]
124 fn test_bow_out_zero() {
125 let m = new_bow_leg_morph();
126 assert!((bow_leg_bow_out(&m) - 0.0).abs() < 1e-6 );
127 }
128
129 #[test]
130 fn test_bow_out_nonzero() {
131 let mut m = new_bow_leg_morph();
132 bow_leg_set_varus(&mut m, 1.0);
133 m.intensity = 0.5;
134 assert!((bow_leg_bow_out(&m) - 0.5).abs() < 1e-6 );
135 }
136
137 #[test]
138 fn test_json_key() {
139 let m = new_bow_leg_morph();
140 let j = bow_leg_to_json(&m);
141 assert!(j.contains("varus_angle") );
142 }
143
144 #[test]
145 fn test_default_symmetric() {
146 let m = BowLegMorph::default();
147 assert!(m.symmetric );
148 }
149}