ifc_structural/member/
varying.rs1use ifc_model::{EntityId, Value};
4
5use crate::error::{StructuralError, StructuralResult};
6use crate::member::{Member, MemberKind};
7
8impl Member<'_, '_> {
9 #[must_use]
11 pub fn is_varying(&self) -> bool {
12 matches!(
13 self.kind,
14 MemberKind::CurveVarying | MemberKind::SurfaceVarying
15 )
16 }
17
18 pub fn subsequent_thicknesses(&self) -> StructuralResult<Option<Vec<f64>>> {
23 if self.kind != MemberKind::SurfaceVarying
24 || !self.record.has_attribute("SubsequentThickness")
25 {
26 return Ok(None);
27 }
28 if self.thickness()?.is_none() {
29 return Err(StructuralError::SemanticViolation {
30 entity: Some(self.record.id),
31 rule: "IfcStructuralSurfaceMemberVarying.WR61",
32 });
33 }
34 let values = match self.record.value("SubsequentThickness")?.unwrap_typed() {
35 Value::List(values) => values,
36 _ => {
37 return Err(StructuralError::InvalidValue {
38 entity: self.record.id,
39 attribute: "SubsequentThickness",
40 expected: "LIST [2:?] of positive finite thickness measures",
41 })
42 }
43 };
44 if values.len() < 2 {
45 return Err(StructuralError::InvalidCardinality {
46 entity: self.record.id,
47 attribute: "SubsequentThickness",
48 minimum: 2,
49 maximum: None,
50 actual: values.len(),
51 });
52 }
53 let mut thicknesses = Vec::with_capacity(values.len());
54 for value in values {
55 let number = match value.unwrap_typed() {
56 Value::Integer(value) => *value as f64,
57 Value::Real(value) => *value,
58 _ => {
59 return Err(StructuralError::InvalidValue {
60 entity: self.record.id,
61 attribute: "SubsequentThickness",
62 expected: "LIST [2:?] of positive finite thickness measures",
63 })
64 }
65 };
66 if !number.is_finite() || number <= 0.0 {
67 return Err(StructuralError::InvalidValue {
68 entity: self.record.id,
69 attribute: "SubsequentThickness",
70 expected: "LIST [2:?] of positive finite thickness measures",
71 });
72 }
73 thicknesses.push(number);
74 }
75 Ok(Some(thicknesses))
76 }
77
78 pub fn varying_thickness_location(&self) -> StructuralResult<Option<EntityId>> {
82 if self.kind != MemberKind::SurfaceVarying
83 || !self.record.has_attribute("VaryingThicknessLocation")
84 {
85 return Ok(None);
86 }
87 self.record
88 .required_ref("VaryingThicknessLocation", "IfcShapeAspect")
89 .map(Some)
90 }
91}