oxihuman_morph/
sideburn_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct SideburnMorph {
10 pub length: f32,
11 pub width: f32,
12 pub taper: f32,
13 pub density: f32,
14}
15
16impl SideburnMorph {
17 pub fn new() -> Self {
18 Self {
19 length: 0.5,
20 width: 0.4,
21 taper: 0.5,
22 density: 0.5,
23 }
24 }
25}
26
27impl Default for SideburnMorph {
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33pub fn new_sideburn_morph() -> SideburnMorph {
35 SideburnMorph::new()
36}
37
38pub fn sideburn_set_length(morph: &mut SideburnMorph, length: f32) {
40 morph.length = length.clamp(0.0, 1.0);
41}
42
43pub fn sideburn_set_width(morph: &mut SideburnMorph, width: f32) {
45 morph.width = width.clamp(0.0, 1.0);
46}
47
48pub fn sideburn_set_taper(morph: &mut SideburnMorph, taper: f32) {
50 morph.taper = taper.clamp(0.0, 1.0);
51}
52
53pub fn sideburn_area_estimate(morph: &SideburnMorph) -> f32 {
55 let avg_width = morph.width * (1.0 - morph.taper * 0.5);
56 morph.length * avg_width
57}
58
59pub fn sideburn_morph_to_json(morph: &SideburnMorph) -> String {
61 format!(
62 r#"{{"length":{:.4},"width":{:.4},"taper":{:.4},"density":{:.4}}}"#,
63 morph.length, morph.width, morph.taper, morph.density
64 )
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn test_defaults() {
73 let m = new_sideburn_morph();
74 assert!((m.width - 0.4).abs() < 1e-6);
75 }
76
77 #[test]
78 fn test_length_clamp() {
79 let mut m = new_sideburn_morph();
80 sideburn_set_length(&mut m, 2.0);
81 assert_eq!(m.length, 1.0);
82 }
83
84 #[test]
85 fn test_width_set() {
86 let mut m = new_sideburn_morph();
87 sideburn_set_width(&mut m, 0.6);
88 assert!((m.width - 0.6).abs() < 1e-6);
89 }
90
91 #[test]
92 fn test_taper_set() {
93 let mut m = new_sideburn_morph();
94 sideburn_set_taper(&mut m, 0.8);
95 assert!((m.taper - 0.8).abs() < 1e-6);
96 }
97
98 #[test]
99 fn test_area_estimate_positive() {
100 let m = new_sideburn_morph();
101 assert!(sideburn_area_estimate(&m) >= 0.0);
102 }
103
104 #[test]
105 fn test_area_zero_length() {
106 let mut m = new_sideburn_morph();
107 sideburn_set_length(&mut m, 0.0);
108 assert_eq!(sideburn_area_estimate(&m), 0.0);
109 }
110
111 #[test]
112 fn test_json() {
113 let m = new_sideburn_morph();
114 let s = sideburn_morph_to_json(&m);
115 assert!(s.contains("taper"));
116 }
117
118 #[test]
119 fn test_clone() {
120 let m = new_sideburn_morph();
121 let m2 = m.clone();
122 assert!((m2.taper - m.taper).abs() < 1e-6);
123 }
124
125 #[test]
126 fn test_default_trait() {
127 let m: SideburnMorph = Default::default();
128 assert!((m.density - 0.5).abs() < 1e-6);
129 }
130}