use axiolid_core::Scalar;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct RectangleProfile {
pub x: Scalar,
pub y: Scalar,
pub thickness: Option<Scalar>,
pub outer_radius: Option<Scalar>,
pub inner_radius: Option<Scalar>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct CircleProfile {
pub radius: Scalar,
pub thickness: Option<Scalar>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct EllipseProfile {
pub semi_axis_x: Scalar,
pub semi_axis_y: Scalar,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum SectionProfile {
I {
depth: Scalar,
width: Scalar,
web_thickness: Scalar,
flange_thickness: Scalar,
fillet_radius: Option<Scalar>,
flange_edge_radius: Option<Scalar>,
flange_slope: Option<Scalar>,
},
AsymmetricI {
depth: Scalar,
web_thickness: Scalar,
bottom_flange_width: Scalar,
bottom_flange_thickness: Scalar,
bottom_fillet_radius: Option<Scalar>,
bottom_flange_edge_radius: Option<Scalar>,
bottom_flange_slope: Option<Scalar>,
top_flange_width: Scalar,
top_flange_thickness: Option<Scalar>,
top_fillet_radius: Option<Scalar>,
top_flange_edge_radius: Option<Scalar>,
top_flange_slope: Option<Scalar>,
},
L {
depth: Scalar,
width: Option<Scalar>,
thickness: Scalar,
fillet_radius: Option<Scalar>,
edge_radius: Option<Scalar>,
leg_slope: Option<Scalar>,
},
T {
depth: Scalar,
flange_width: Scalar,
web_thickness: Scalar,
flange_thickness: Scalar,
fillet_radius: Option<Scalar>,
flange_edge_radius: Option<Scalar>,
web_edge_radius: Option<Scalar>,
web_slope: Option<Scalar>,
flange_slope: Option<Scalar>,
},
U {
depth: Scalar,
flange_width: Scalar,
web_thickness: Scalar,
flange_thickness: Scalar,
fillet_radius: Option<Scalar>,
edge_radius: Option<Scalar>,
flange_slope: Option<Scalar>,
},
C {
depth: Scalar,
width: Scalar,
wall_thickness: Scalar,
girth: Scalar,
internal_fillet_radius: Option<Scalar>,
},
Z {
depth: Scalar,
flange_width: Scalar,
web_thickness: Scalar,
flange_thickness: Scalar,
fillet_radius: Option<Scalar>,
edge_radius: Option<Scalar>,
},
Trapezium {
bottom_x: Scalar,
top_x: Scalar,
y: Scalar,
top_offset: Scalar,
},
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn an_asymmetric_i_is_a_distinct_variant_from_a_symmetric_one() {
let symmetric = SectionProfile::I {
depth: 0.4,
width: 0.3,
web_thickness: 0.011,
flange_thickness: 0.019,
fillet_radius: Some(0.021),
flange_edge_radius: None,
flange_slope: None,
};
let asymmetric = SectionProfile::AsymmetricI {
depth: 0.4,
web_thickness: 0.011,
bottom_flange_width: 0.3,
bottom_flange_thickness: 0.019,
bottom_fillet_radius: Some(0.021),
bottom_flange_edge_radius: None,
bottom_flange_slope: None,
top_flange_width: 0.2,
top_flange_thickness: Some(0.019),
top_fillet_radius: Some(0.021),
top_flange_edge_radius: None,
top_flange_slope: None,
};
assert_ne!(symmetric, asymmetric);
}
#[test]
fn an_absent_fillet_differs_from_a_declared_zero() {
let make = |fillet| SectionProfile::U {
depth: 0.3,
flange_width: 0.1,
web_thickness: 0.0075,
flange_thickness: 0.0125,
fillet_radius: fillet,
edge_radius: None,
flange_slope: None,
};
assert_ne!(make(None), make(Some(0.0)));
assert_eq!(make(Some(0.015)), make(Some(0.015)));
}
#[test]
fn a_section_wraps_into_a_profile_without_loss() {
let section = SectionProfile::L {
depth: 0.1,
width: None,
thickness: 0.008,
fillet_radius: Some(0.012),
edge_radius: Some(0.006),
leg_slope: None,
};
let profile = crate::Profile::Section(section.clone());
match profile {
crate::Profile::Section(round_tripped) => assert_eq!(section, round_tripped),
other => panic!("expected a section, got {other:?}"),
}
}
}