oxihuman_export/
capsule_export.rs1#![allow(dead_code)]
4
5use std::f32::consts::PI;
6
7#[allow(dead_code)]
9pub struct CapsuleExport {
10 pub name: String,
11 pub center: [f32; 3],
12 pub axis: [f32; 3],
13 pub radius: f32,
14 pub half_height: f32,
15}
16
17#[allow(dead_code)]
18pub struct CapsuleBundle {
19 pub capsules: Vec<CapsuleExport>,
20}
21
22#[allow(dead_code)]
23pub fn new_capsule_bundle() -> CapsuleBundle {
24 CapsuleBundle { capsules: vec![] }
25}
26
27#[allow(dead_code)]
28pub fn add_capsule(bundle: &mut CapsuleBundle, cap: CapsuleExport) {
29 bundle.capsules.push(cap);
30}
31
32#[allow(dead_code)]
33pub fn capsule_count(bundle: &CapsuleBundle) -> usize {
34 bundle.capsules.len()
35}
36
37#[allow(dead_code)]
38pub fn capsule_volume(cap: &CapsuleExport) -> f32 {
39 let r = cap.radius;
40 let h = cap.half_height * 2.0;
41 PI * r * r * h + (4.0 / 3.0) * PI * r * r * r
43}
44
45#[allow(dead_code)]
46pub fn capsule_surface_area(cap: &CapsuleExport) -> f32 {
47 let r = cap.radius;
48 let h = cap.half_height * 2.0;
49 2.0 * PI * r * h + 4.0 * PI * r * r
50}
51
52#[allow(dead_code)]
53pub fn capsule_total_length(cap: &CapsuleExport) -> f32 {
54 cap.half_height * 2.0 + cap.radius * 2.0
55}
56
57#[allow(dead_code)]
58pub fn capsule_to_json(cap: &CapsuleExport) -> String {
59 format!(
60 "{{\"name\":\"{}\",\"radius\":{},\"half_height\":{},\"center\":[{},{},{}]}}",
61 cap.name, cap.radius, cap.half_height, cap.center[0], cap.center[1], cap.center[2]
62 )
63}
64
65#[allow(dead_code)]
66pub fn capsule_bundle_to_json(bundle: &CapsuleBundle) -> String {
67 format!("{{\"capsule_count\":{}}}", bundle.capsules.len())
68}
69
70#[allow(dead_code)]
71pub fn validate_capsule(cap: &CapsuleExport) -> bool {
72 cap.radius > 0.0 && cap.half_height >= 0.0 && !cap.name.is_empty()
73}
74
75#[allow(dead_code)]
76pub fn find_capsule_by_name<'a>(
77 bundle: &'a CapsuleBundle,
78 name: &str,
79) -> Option<&'a CapsuleExport> {
80 bundle.capsules.iter().find(|c| c.name == name)
81}
82
83#[allow(dead_code)]
84pub fn default_capsule(name: &str) -> CapsuleExport {
85 CapsuleExport {
86 name: name.to_string(),
87 center: [0.0; 3],
88 axis: [0.0, 1.0, 0.0],
89 radius: 0.1,
90 half_height: 0.5,
91 }
92}
93
94#[allow(dead_code)]
95pub fn total_capsule_volume(bundle: &CapsuleBundle) -> f32 {
96 bundle.capsules.iter().map(capsule_volume).sum()
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 fn arm_capsule() -> CapsuleExport {
104 default_capsule("upper_arm")
105 }
106
107 #[test]
108 fn test_add_capsule() {
109 let mut b = new_capsule_bundle();
110 add_capsule(&mut b, arm_capsule());
111 assert_eq!(capsule_count(&b), 1);
112 }
113
114 #[test]
115 fn test_capsule_volume_positive() {
116 let cap = arm_capsule();
117 assert!(capsule_volume(&cap) > 0.0);
118 }
119
120 #[test]
121 fn test_capsule_surface_area_positive() {
122 let cap = arm_capsule();
123 assert!(capsule_surface_area(&cap) > 0.0);
124 }
125
126 #[test]
127 fn test_capsule_total_length() {
128 let cap = arm_capsule();
129 let expected = cap.half_height * 2.0 + cap.radius * 2.0;
130 assert!((capsule_total_length(&cap) - expected).abs() < 1e-5);
131 }
132
133 #[test]
134 fn test_validate_capsule() {
135 let cap = arm_capsule();
136 assert!(validate_capsule(&cap));
137 }
138
139 #[test]
140 fn test_find_capsule_found() {
141 let mut b = new_capsule_bundle();
142 add_capsule(&mut b, arm_capsule());
143 assert!(find_capsule_by_name(&b, "upper_arm").is_some());
144 }
145
146 #[test]
147 fn test_find_capsule_missing() {
148 let b = new_capsule_bundle();
149 assert!(find_capsule_by_name(&b, "arm").is_none());
150 }
151
152 #[test]
153 fn test_total_volume() {
154 let mut b = new_capsule_bundle();
155 add_capsule(&mut b, arm_capsule());
156 add_capsule(&mut b, arm_capsule());
157 let single = capsule_volume(&arm_capsule());
158 assert!((total_capsule_volume(&b) - 2.0 * single).abs() < 1e-5);
159 }
160
161 #[test]
162 fn test_to_json() {
163 let cap = arm_capsule();
164 let j = capsule_to_json(&cap);
165 assert!(j.contains("upper_arm"));
166 assert!(j.contains("radius"));
167 }
168
169 #[test]
170 fn test_bundle_to_json() {
171 let mut b = new_capsule_bundle();
172 add_capsule(&mut b, arm_capsule());
173 let j = capsule_bundle_to_json(&b);
174 assert!(j.contains("capsule_count"));
175 }
176}