oxihuman_morph/
vitiligo_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum VitiligoPaattern {
10 Focal,
11 Segmental,
12 Generalized,
13 Universal,
14}
15
16#[derive(Debug, Clone)]
18pub struct VitilligoPatch {
19 pub position: [f32; 3],
20 pub radius: f32,
21 pub depigmentation: f32,
22}
23
24#[derive(Debug, Clone)]
26pub struct VitiligoMorph {
27 pub pattern: VitiligoPaattern,
28 pub patches: Vec<VitilligoPatch>,
29 pub global_extent: f32,
30 pub morph_count: usize,
31 pub enabled: bool,
32}
33
34impl VitiligoMorph {
35 pub fn new(morph_count: usize) -> Self {
36 VitiligoMorph {
37 pattern: VitiligoPaattern::Focal,
38 patches: Vec::new(),
39 global_extent: 0.0,
40 morph_count,
41 enabled: true,
42 }
43 }
44}
45
46pub fn new_vitiligo_morph(morph_count: usize) -> VitiligoMorph {
48 VitiligoMorph::new(morph_count)
49}
50
51pub fn vim_set_pattern(morph: &mut VitiligoMorph, pattern: VitiligoPaattern) {
53 morph.pattern = pattern;
54}
55
56pub fn vim_add_patch(morph: &mut VitiligoMorph, patch: VitilligoPatch) {
58 morph.patches.push(patch);
59}
60
61pub fn vim_set_extent(morph: &mut VitiligoMorph, extent: f32) {
63 morph.global_extent = extent.clamp(0.0, 1.0);
64}
65
66pub fn vim_clear(morph: &mut VitiligoMorph) {
68 morph.patches.clear();
69}
70
71pub fn vim_evaluate(morph: &VitiligoMorph) -> Vec<f32> {
73 if !morph.enabled || morph.morph_count == 0 {
75 return vec![];
76 }
77 vec![morph.global_extent; morph.morph_count]
78}
79
80pub fn vim_set_enabled(morph: &mut VitiligoMorph, enabled: bool) {
82 morph.enabled = enabled;
83}
84
85pub fn vim_patch_count(morph: &VitiligoMorph) -> usize {
87 morph.patches.len()
88}
89
90pub fn vim_to_json(morph: &VitiligoMorph) -> String {
92 let pat = match morph.pattern {
93 VitiligoPaattern::Focal => "focal",
94 VitiligoPaattern::Segmental => "segmental",
95 VitiligoPaattern::Generalized => "generalized",
96 VitiligoPaattern::Universal => "universal",
97 };
98 format!(
99 r#"{{"pattern":"{}","patch_count":{},"global_extent":{},"morph_count":{},"enabled":{}}}"#,
100 pat,
101 morph.patches.len(),
102 morph.global_extent,
103 morph.morph_count,
104 morph.enabled
105 )
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 fn make_patch() -> VitilligoPatch {
113 VitilligoPatch {
114 position: [0.2, 0.5, 0.1],
115 radius: 0.05,
116 depigmentation: 1.0,
117 }
118 }
119
120 #[test]
121 fn test_default_pattern() {
122 let m = new_vitiligo_morph(4);
123 assert_eq!(
124 m.pattern,
125 VitiligoPaattern::Focal );
127 }
128
129 #[test]
130 fn test_set_pattern() {
131 let mut m = new_vitiligo_morph(4);
132 vim_set_pattern(&mut m, VitiligoPaattern::Universal);
133 assert_eq!(
134 m.pattern,
135 VitiligoPaattern::Universal );
137 }
138
139 #[test]
140 fn test_add_patch() {
141 let mut m = new_vitiligo_morph(4);
142 vim_add_patch(&mut m, make_patch());
143 assert_eq!(vim_patch_count(&m), 1 );
144 }
145
146 #[test]
147 fn test_clear() {
148 let mut m = new_vitiligo_morph(4);
149 vim_add_patch(&mut m, make_patch());
150 vim_clear(&mut m);
151 assert_eq!(vim_patch_count(&m), 0 );
152 }
153
154 #[test]
155 fn test_extent_clamp() {
156 let mut m = new_vitiligo_morph(4);
157 vim_set_extent(&mut m, 1.5);
158 assert!((m.global_extent - 1.0).abs() < 1e-6 );
159 }
160
161 #[test]
162 fn test_evaluate_length() {
163 let mut m = new_vitiligo_morph(6);
164 vim_set_extent(&mut m, 0.5);
165 assert_eq!(
166 vim_evaluate(&m).len(),
167 6 );
169 }
170
171 #[test]
172 fn test_evaluate_disabled() {
173 let mut m = new_vitiligo_morph(4);
174 vim_set_enabled(&mut m, false);
175 assert!(vim_evaluate(&m).is_empty() );
176 }
177
178 #[test]
179 fn test_to_json_has_pattern() {
180 let m = new_vitiligo_morph(4);
181 let j = vim_to_json(&m);
182 assert!(j.contains("\"pattern\"") );
183 }
184
185 #[test]
186 fn test_enabled_default() {
187 let m = new_vitiligo_morph(4);
188 assert!(m.enabled );
189 }
190
191 #[test]
192 fn test_evaluate_matches_extent() {
193 let mut m = new_vitiligo_morph(3);
194 vim_set_extent(&mut m, 0.5);
195 let out = vim_evaluate(&m);
196 assert!((out[0] - 0.5).abs() < 1e-5 );
197 }
198}