oxihuman_morph/
styloid_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
7pub struct StyloidMorph {
8 pub length: f32,
10 pub angle_offset: f32,
12 pub tip_sharpness: f32,
14}
15
16pub fn new_styloid_morph() -> StyloidMorph {
17 StyloidMorph {
18 length: 0.0,
19 angle_offset: 0.0,
20 tip_sharpness: 0.0,
21 }
22}
23
24pub fn sty_set_length(m: &mut StyloidMorph, v: f32) {
25 m.length = v.clamp(0.0, 1.0);
26}
27
28pub fn sty_set_angle_offset(m: &mut StyloidMorph, v: f32) {
29 m.angle_offset = v.clamp(-1.0, 1.0);
30}
31
32pub fn sty_set_tip_sharpness(m: &mut StyloidMorph, v: f32) {
33 m.tip_sharpness = v.clamp(0.0, 1.0);
34}
35
36pub fn sty_overall_weight(m: &StyloidMorph) -> f32 {
37 (m.length + m.angle_offset.abs() + m.tip_sharpness) / 3.0
38}
39
40pub fn sty_blend(a: &StyloidMorph, b: &StyloidMorph, t: f32) -> StyloidMorph {
41 let t = t.clamp(0.0, 1.0);
42 StyloidMorph {
43 length: a.length + (b.length - a.length) * t,
44 angle_offset: a.angle_offset + (b.angle_offset - a.angle_offset) * t,
45 tip_sharpness: a.tip_sharpness + (b.tip_sharpness - a.tip_sharpness) * t,
46 }
47}
48
49pub fn sty_is_neutral(m: &StyloidMorph) -> bool {
50 m.length < 1e-5 && m.angle_offset.abs() < 1e-5 && m.tip_sharpness < 1e-5
51}
52
53pub fn sty_to_json(m: &StyloidMorph) -> String {
54 format!(
55 r#"{{"length":{:.4},"angle_offset":{:.4},"tip_sharpness":{:.4}}}"#,
56 m.length, m.angle_offset, m.tip_sharpness
57 )
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn test_new_defaults() {
66 let m = new_styloid_morph();
68 assert_eq!(m.length, 0.0);
69 assert_eq!(m.angle_offset, 0.0);
70 assert_eq!(m.tip_sharpness, 0.0);
71 }
72
73 #[test]
74 fn test_set_length() {
75 let mut m = new_styloid_morph();
77 sty_set_length(&mut m, 0.5);
78 assert!((m.length - 0.5).abs() < 1e-6);
79 }
80
81 #[test]
82 fn test_length_clamp_high() {
83 let mut m = new_styloid_morph();
85 sty_set_length(&mut m, 2.0);
86 assert_eq!(m.length, 1.0);
87 }
88
89 #[test]
90 fn test_angle_offset_clamp() {
91 let mut m = new_styloid_morph();
93 sty_set_angle_offset(&mut m, -5.0);
94 assert_eq!(m.angle_offset, -1.0);
95 }
96
97 #[test]
98 fn test_is_neutral_true() {
99 assert!(sty_is_neutral(&new_styloid_morph()));
101 }
102
103 #[test]
104 fn test_is_neutral_false() {
105 let mut m = new_styloid_morph();
107 sty_set_length(&mut m, 0.2);
108 assert!(!sty_is_neutral(&m));
109 }
110
111 #[test]
112 fn test_overall_weight() {
113 let m = StyloidMorph {
115 length: 0.9,
116 angle_offset: 0.0,
117 tip_sharpness: 0.9,
118 };
119 assert!((sty_overall_weight(&m) - 0.6).abs() < 1e-5);
120 }
121
122 #[test]
123 fn test_blend() {
124 let a = new_styloid_morph();
126 let b = StyloidMorph {
127 length: 1.0,
128 angle_offset: 0.5,
129 tip_sharpness: 0.8,
130 };
131 let c = sty_blend(&a, &b, 1.0);
132 assert!((c.length - 1.0).abs() < 1e-6);
133 }
134
135 #[test]
136 fn test_to_json() {
137 assert!(sty_to_json(&new_styloid_morph()).contains("length"));
139 }
140
141 #[test]
142 fn test_clone() {
143 let m = StyloidMorph {
145 length: 0.3,
146 angle_offset: 0.2,
147 tip_sharpness: 0.1,
148 };
149 let m2 = m.clone();
150 assert_eq!(m.length, m2.length);
151 }
152}