oxihuman_morph/
edema_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum EdemaType {
10 Pitting,
11 NonPitting,
12 Lymphedema,
13 Angioedema,
14}
15
16#[derive(Debug, Clone)]
18pub struct EdemaRegion {
19 pub edema_type: EdemaType,
20 pub position: [f32; 3],
21 pub radius: f32,
22 pub swelling: f32,
23}
24
25#[derive(Debug, Clone)]
27pub struct EdemaMorph {
28 pub regions: Vec<EdemaRegion>,
29 pub global_intensity: f32,
30 pub morph_count: usize,
31 pub enabled: bool,
32}
33
34impl EdemaMorph {
35 pub fn new(morph_count: usize) -> Self {
36 EdemaMorph {
37 regions: Vec::new(),
38 global_intensity: 0.0,
39 morph_count,
40 enabled: true,
41 }
42 }
43}
44
45pub fn new_edema_morph(morph_count: usize) -> EdemaMorph {
47 EdemaMorph::new(morph_count)
48}
49
50pub fn edm_add_region(morph: &mut EdemaMorph, region: EdemaRegion) {
52 morph.regions.push(region);
53}
54
55pub fn edm_set_intensity(morph: &mut EdemaMorph, intensity: f32) {
57 morph.global_intensity = intensity.clamp(0.0, 1.0);
58}
59
60pub fn edm_clear(morph: &mut EdemaMorph) {
62 morph.regions.clear();
63}
64
65pub fn edm_evaluate(morph: &EdemaMorph) -> Vec<f32> {
67 if !morph.enabled || morph.morph_count == 0 {
69 return vec![];
70 }
71 vec![morph.global_intensity; morph.morph_count]
72}
73
74pub fn edm_set_enabled(morph: &mut EdemaMorph, enabled: bool) {
76 morph.enabled = enabled;
77}
78
79pub fn edm_region_count(morph: &EdemaMorph) -> usize {
81 morph.regions.len()
82}
83
84pub fn edm_to_json(morph: &EdemaMorph) -> String {
86 format!(
87 r#"{{"region_count":{},"global_intensity":{},"morph_count":{},"enabled":{}}}"#,
88 morph.regions.len(),
89 morph.global_intensity,
90 morph.morph_count,
91 morph.enabled
92 )
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 fn make_region() -> EdemaRegion {
100 EdemaRegion {
101 edema_type: EdemaType::Pitting,
102 position: [0.0, 0.0, 0.0],
103 radius: 0.1,
104 swelling: 0.5,
105 }
106 }
107
108 #[test]
109 fn test_initial_empty() {
110 let m = new_edema_morph(4);
111 assert_eq!(edm_region_count(&m), 0 );
112 }
113
114 #[test]
115 fn test_add_region() {
116 let mut m = new_edema_morph(4);
117 edm_add_region(&mut m, make_region());
118 assert_eq!(edm_region_count(&m), 1 );
119 }
120
121 #[test]
122 fn test_clear() {
123 let mut m = new_edema_morph(4);
124 edm_add_region(&mut m, make_region());
125 edm_clear(&mut m);
126 assert_eq!(edm_region_count(&m), 0 );
127 }
128
129 #[test]
130 fn test_intensity_clamp() {
131 let mut m = new_edema_morph(4);
132 edm_set_intensity(&mut m, 1.5);
133 assert!((m.global_intensity - 1.0).abs() < 1e-6 );
134 }
135
136 #[test]
137 fn test_evaluate_length() {
138 let mut m = new_edema_morph(5);
139 edm_set_intensity(&mut m, 0.8);
140 assert_eq!(
141 edm_evaluate(&m).len(),
142 5 );
144 }
145
146 #[test]
147 fn test_evaluate_disabled() {
148 let mut m = new_edema_morph(4);
149 edm_set_enabled(&mut m, false);
150 assert!(edm_evaluate(&m).is_empty() );
151 }
152
153 #[test]
154 fn test_to_json_has_region_count() {
155 let m = new_edema_morph(4);
156 let j = edm_to_json(&m);
157 assert!(j.contains("\"region_count\"") );
158 }
159
160 #[test]
161 fn test_enabled_default() {
162 let m = new_edema_morph(4);
163 assert!(m.enabled );
164 }
165
166 #[test]
167 fn test_evaluate_matches_intensity() {
168 let mut m = new_edema_morph(3);
169 edm_set_intensity(&mut m, 0.3);
170 let out = edm_evaluate(&m);
171 assert!((out[0] - 0.3).abs() < 1e-5 );
172 }
173}