use ifc_model::EntityId;
use crate::error::{StructuralError, StructuralResult};
use crate::view::Record;
mod dynamic;
mod reinforcement;
pub use dynamic::LoadConfiguration;
pub use reinforcement::SurfaceReinforcementArea;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum LoadKind {
SingleForce,
SingleForceWarping,
SingleDisplacement,
SingleDisplacementDistortion,
LinearForce,
PlanarForce,
Temperature,
}
#[derive(Debug, Clone, Copy)]
pub struct StaticLoad<'m, 's> {
record: Record<'m, 's>,
kind: LoadKind,
}
impl<'m, 's> StaticLoad<'m, 's> {
pub(crate) fn from_record(record: Record<'m, 's>) -> StructuralResult<Self> {
const ORDER: [(&str, LoadKind); 7] = [
(
"IfcStructuralLoadSingleForceWarping",
LoadKind::SingleForceWarping,
),
("IfcStructuralLoadSingleForce", LoadKind::SingleForce),
(
"IfcStructuralLoadSingleDisplacementDistortion",
LoadKind::SingleDisplacementDistortion,
),
(
"IfcStructuralLoadSingleDisplacement",
LoadKind::SingleDisplacement,
),
("IfcStructuralLoadLinearForce", LoadKind::LinearForce),
("IfcStructuralLoadPlanarForce", LoadKind::PlanarForce),
("IfcStructuralLoadTemperature", LoadKind::Temperature),
];
let Some(kind) = ORDER
.iter()
.find(|(ancestor, _)| record.schema.is_a(&record.entity.type_name, ancestor))
.map(|(_, kind)| *kind)
else {
return Err(StructuralError::WrongType {
id: record.id,
expected: "core static structural load",
actual: record.entity.type_name.to_string(),
});
};
Ok(Self { record, kind })
}
#[must_use]
pub fn id(&self) -> EntityId {
self.record.id
}
#[must_use]
pub fn kind(&self) -> LoadKind {
self.kind
}
pub fn name(&self) -> StructuralResult<Option<&'m str>> {
self.record.optional_text("Name")
}
pub fn components(&self) -> StructuralResult<Vec<Option<f64>>> {
let names: &[&'static str] = match self.kind {
LoadKind::SingleForce => &[
"ForceX", "ForceY", "ForceZ", "MomentX", "MomentY", "MomentZ",
],
LoadKind::SingleForceWarping => &[
"ForceX",
"ForceY",
"ForceZ",
"MomentX",
"MomentY",
"MomentZ",
"WarpingMoment",
],
LoadKind::SingleDisplacement => &[
"DisplacementX",
"DisplacementY",
"DisplacementZ",
"RotationalDisplacementRX",
"RotationalDisplacementRY",
"RotationalDisplacementRZ",
],
LoadKind::SingleDisplacementDistortion => &[
"DisplacementX",
"DisplacementY",
"DisplacementZ",
"RotationalDisplacementRX",
"RotationalDisplacementRY",
"RotationalDisplacementRZ",
"Distortion",
],
LoadKind::LinearForce => &[
"LinearForceX",
"LinearForceY",
"LinearForceZ",
"LinearMomentX",
"LinearMomentY",
"LinearMomentZ",
],
LoadKind::PlanarForce => &["PlanarForceX", "PlanarForceY", "PlanarForceZ"],
LoadKind::Temperature => {
if self.record.has_attribute("DeltaTConstant") {
&["DeltaTConstant", "DeltaTY", "DeltaTZ"]
} else {
&["DeltaT_Constant", "DeltaT_Y", "DeltaT_Z"]
}
}
};
names
.iter()
.map(|name| self.record.optional_number(name))
.collect()
}
}