1use super::*;
14
15#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
22pub struct Haunch {
23 pub length: f64,
25 #[serde(default)]
27 pub depth_increase: f64,
28 #[serde(default)]
30 pub width_increase: f64,
31}
32
33#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
35pub enum JointKind {
36 #[default]
38 Site,
39 Shop,
41}
42
43#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
49pub struct MemberJoint {
50 pub distance: f64,
52 #[serde(default)]
54 pub kind: JointKind,
55}
56
57#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
60pub struct MemberDetailAttr {
61 pub elem: ElemId,
62 #[serde(default)]
64 pub haunch_i: Option<Haunch>,
65 #[serde(default)]
67 pub haunch_j: Option<Haunch>,
68 #[serde(default)]
70 pub joints: Vec<MemberJoint>,
71}
72
73impl MemberDetailAttr {
74 pub fn new(elem: ElemId) -> Self {
76 Self {
77 elem,
78 haunch_i: None,
79 haunch_j: None,
80 joints: Vec::new(),
81 }
82 }
83
84 pub fn is_empty(&self) -> bool {
86 self.haunch_i.is_none() && self.haunch_j.is_none() && self.joints.is_empty()
87 }
88
89 pub fn extra_check_positions(&self, rigid_zone: &RigidZone, geom_len: f64) -> Vec<f64> {
102 if geom_len <= 1e-12 {
103 return Vec::new();
104 }
105 let mut xs = Vec::new();
106 if let Some(h) = &self.haunch_i {
107 if h.length > 0.0 {
108 let base = rigid_zone.face_i_or_zero();
111 xs.push(((base + h.length) / geom_len).clamp(0.0, 0.5 - 1e-9));
112 }
113 }
114 if let Some(h) = &self.haunch_j {
115 if h.length > 0.0 {
116 let base = rigid_zone.face_j_or_zero();
117 xs.push((1.0 - (base + h.length) / geom_len).clamp(0.5 + 1e-9, 1.0));
118 }
119 }
120 for j in &self.joints {
121 let xi = j.distance / geom_len;
122 if xi > 0.0 && xi < 1.0 {
123 xs.push(xi);
124 }
125 }
126 xs
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 fn rigid(face_i: f64, face_j: f64) -> RigidZone {
135 RigidZone {
136 face_i: Some(face_i),
137 face_j: Some(face_j),
138 ..Default::default()
139 }
140 }
141
142 #[test]
145 fn test_extra_check_positions() {
146 let attr = MemberDetailAttr {
147 elem: ElemId(0),
148 haunch_i: Some(Haunch {
149 length: 700.0,
150 depth_increase: 200.0,
151 width_increase: 0.0,
152 }),
153 haunch_j: Some(Haunch {
154 length: 500.0,
155 depth_increase: 200.0,
156 width_increase: 0.0,
157 }),
158 joints: vec![MemberJoint {
159 distance: 1000.0,
160 kind: JointKind::Site,
161 }],
162 };
163 let xs = attr.extra_check_positions(&rigid(300.0, 250.0), 4000.0);
164 assert_eq!(xs.len(), 3);
167 assert!((xs[0] - 0.25).abs() < 1e-12);
168 assert!((xs[1] - 0.8125).abs() < 1e-12);
169 assert!((xs[2] - 0.25).abs() < 1e-12);
170 }
171
172 #[test]
175 fn test_extra_check_positions_invalid_input() {
176 let attr = MemberDetailAttr {
177 elem: ElemId(0),
178 haunch_i: Some(Haunch {
179 length: 0.0,
180 depth_increase: 100.0,
181 width_increase: 0.0,
182 }),
183 haunch_j: None,
184 joints: vec![
185 MemberJoint {
186 distance: 0.0,
187 kind: JointKind::Site,
188 },
189 MemberJoint {
190 distance: 5000.0,
191 kind: JointKind::Shop,
192 },
193 ],
194 };
195 assert!(attr
196 .extra_check_positions(&rigid(300.0, 300.0), 4000.0)
197 .is_empty());
198 assert!(attr
199 .extra_check_positions(&rigid(300.0, 300.0), 0.0)
200 .is_empty());
201 }
202
203 #[test]
206 fn test_extra_check_positions_clamped() {
207 let attr = MemberDetailAttr {
208 elem: ElemId(0),
209 haunch_i: Some(Haunch {
210 length: 3000.0,
211 depth_increase: 0.0,
212 width_increase: 0.0,
213 }),
214 haunch_j: Some(Haunch {
215 length: 3000.0,
216 depth_increase: 0.0,
217 width_increase: 0.0,
218 }),
219 joints: Vec::new(),
220 };
221 let xs = attr.extra_check_positions(&rigid(0.0, 0.0), 4000.0);
222 assert_eq!(xs.len(), 2);
223 assert!(xs[0] < 0.5);
224 assert!(xs[1] > 0.5);
225 }
226
227 #[test]
229 fn test_is_empty() {
230 let mut attr = MemberDetailAttr::new(ElemId(1));
231 assert!(attr.is_empty());
232 attr.joints.push(MemberJoint {
233 distance: 100.0,
234 kind: JointKind::Shop,
235 });
236 assert!(!attr.is_empty());
237 }
238}