oxihuman_morph/
nose_root_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct NoseRootMorph {
10 pub width: f32,
11 pub depth: f32,
12 pub height: f32,
13 pub bridge_continuity: f32,
14 pub intercanthal_ratio: f32,
15}
16
17impl NoseRootMorph {
18 pub fn new() -> Self {
19 Self {
20 width: 0.5,
21 depth: 0.5,
22 height: 0.5,
23 bridge_continuity: 0.5,
24 intercanthal_ratio: 0.5,
25 }
26 }
27}
28
29impl Default for NoseRootMorph {
30 fn default() -> Self {
31 Self::new()
32 }
33}
34
35pub fn new_nose_root_morph() -> NoseRootMorph {
37 NoseRootMorph::new()
38}
39
40pub fn nroot_set_width(m: &mut NoseRootMorph, v: f32) {
42 m.width = v.clamp(0.0, 1.0);
43}
44
45pub fn nroot_set_depth(m: &mut NoseRootMorph, v: f32) {
47 m.depth = v.clamp(0.0, 1.0);
48}
49
50pub fn nroot_set_height(m: &mut NoseRootMorph, v: f32) {
52 m.height = v.clamp(0.0, 1.0);
53}
54
55pub fn nroot_set_bridge_continuity(m: &mut NoseRootMorph, v: f32) {
57 m.bridge_continuity = v.clamp(0.0, 1.0);
58}
59
60pub fn nroot_aspect_ratio(m: &NoseRootMorph) -> f32 {
62 if m.depth.abs() < 1e-6 {
63 return 0.0;
64 }
65 m.width / m.depth
66}
67
68pub fn nose_root_morph_to_json(m: &NoseRootMorph) -> String {
70 format!(
71 r#"{{"width":{:.4},"depth":{:.4},"height":{:.4},"bridge_continuity":{:.4},"intercanthal_ratio":{:.4}}}"#,
72 m.width, m.depth, m.height, m.bridge_continuity, m.intercanthal_ratio
73 )
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn test_defaults() {
82 let m = new_nose_root_morph();
83 assert!((m.width - 0.5).abs() < 1e-6);
84 assert!((m.depth - 0.5).abs() < 1e-6);
85 }
86
87 #[test]
88 fn test_width_clamp_high() {
89 let mut m = new_nose_root_morph();
90 nroot_set_width(&mut m, 5.0);
91 assert_eq!(m.width, 1.0);
92 }
93
94 #[test]
95 fn test_width_clamp_low() {
96 let mut m = new_nose_root_morph();
97 nroot_set_width(&mut m, -1.0);
98 assert_eq!(m.width, 0.0);
99 }
100
101 #[test]
102 fn test_depth_set() {
103 let mut m = new_nose_root_morph();
104 nroot_set_depth(&mut m, 0.7);
105 assert!((m.depth - 0.7).abs() < 1e-6);
106 }
107
108 #[test]
109 fn test_height_set() {
110 let mut m = new_nose_root_morph();
111 nroot_set_height(&mut m, 0.6);
112 assert!((m.height - 0.6).abs() < 1e-6);
113 }
114
115 #[test]
116 fn test_bridge_continuity_clamp() {
117 let mut m = new_nose_root_morph();
118 nroot_set_bridge_continuity(&mut m, 2.0);
119 assert_eq!(m.bridge_continuity, 1.0);
120 }
121
122 #[test]
123 fn test_aspect_ratio_positive() {
124 let m = new_nose_root_morph();
125 assert!(nroot_aspect_ratio(&m) > 0.0);
126 }
127
128 #[test]
129 fn test_aspect_ratio_zero_depth() {
130 let mut m = new_nose_root_morph();
131 m.depth = 0.0;
132 assert_eq!(nroot_aspect_ratio(&m), 0.0);
133 }
134
135 #[test]
136 fn test_json_keys() {
137 let m = new_nose_root_morph();
138 let s = nose_root_morph_to_json(&m);
139 assert!(s.contains("bridge_continuity"));
140 }
141
142 #[test]
143 fn test_clone() {
144 let m = new_nose_root_morph();
145 let m2 = m.clone();
146 assert!((m2.height - m.height).abs() < 1e-6);
147 }
148}