Skip to main content

ifc_material/layer/
usage.rs

1//! `IfcMaterialLayerSetUsage` authored fields.
2//!
3//! IFC2X3 declares the first four attributes; `ReferenceExtent` is IFC4
4//! onwards.
5
6use ifc_model::EntityId;
7
8use crate::view::{
9    borrowed_entity, optional_number, required_enum, required_number, required_ref, MaterialView,
10};
11use crate::{DirectionSense, LayerSetDirection, MaterialError, MaterialResult};
12
13borrowed_entity!(MaterialLayerSetUsage, "IFCMATERIALLAYERSETUSAGE");
14
15impl MaterialLayerSetUsage<'_> {
16    /// `IfcMaterialLayerSetUsage.ForLayerSet`. Required.
17    pub fn layer_set_id(self) -> MaterialResult<EntityId> {
18        required_ref(
19            "IFCMATERIALLAYERSETUSAGE",
20            self.id(),
21            self.entity(),
22            self.slot("ForLayerSet")?,
23            "ForLayerSet",
24        )
25    }
26
27    /// `IfcMaterialLayerSetUsage.LayerSetDirection`. Required.
28    pub fn layer_set_direction(self) -> MaterialResult<LayerSetDirection> {
29        let token = required_enum(
30            "IFCMATERIALLAYERSETUSAGE",
31            self.id(),
32            self.entity(),
33            self.slot("LayerSetDirection")?,
34            "LayerSetDirection",
35        )?;
36        LayerSetDirection::parse(token).ok_or_else(|| MaterialError::InvalidValue {
37            entity: "IFCMATERIALLAYERSETUSAGE",
38            id: self.id(),
39            attribute: "LayerSetDirection",
40            value: token.to_owned(),
41        })
42    }
43
44    /// `IfcMaterialLayerSetUsage.DirectionSense`. Required.
45    pub fn direction_sense(self) -> MaterialResult<DirectionSense> {
46        let token = required_enum(
47            "IFCMATERIALLAYERSETUSAGE",
48            self.id(),
49            self.entity(),
50            self.slot("DirectionSense")?,
51            "DirectionSense",
52        )?;
53        DirectionSense::parse(token).ok_or_else(|| MaterialError::InvalidValue {
54            entity: "IFCMATERIALLAYERSETUSAGE",
55            id: self.id(),
56            attribute: "DirectionSense",
57            value: token.to_owned(),
58        })
59    }
60
61    /// `IfcMaterialLayerSetUsage.OffsetFromReferenceLine`. Required.
62    pub fn offset_from_reference_line(self) -> MaterialResult<f64> {
63        required_number(
64            "IFCMATERIALLAYERSETUSAGE",
65            self.id(),
66            self.entity(),
67            self.slot("OffsetFromReferenceLine")?,
68            "OffsetFromReferenceLine",
69        )
70    }
71
72    /// `IfcMaterialLayerSetUsage.ReferenceExtent`, if given. Must be
73    /// strictly positive when present. `NotInSchema` for IFC2X3.
74    pub fn reference_extent(self) -> MaterialResult<Option<f64>> {
75        let value = optional_number(
76            "IFCMATERIALLAYERSETUSAGE",
77            self.id(),
78            self.entity(),
79            self.slot("ReferenceExtent")?,
80            "ReferenceExtent",
81        )?;
82        if value.is_some_and(|value| value <= 0.0) {
83            return Err(MaterialError::InvalidValue {
84                entity: "IFCMATERIALLAYERSETUSAGE",
85                id: self.id(),
86                attribute: "ReferenceExtent",
87                value: "expected a positive length".to_owned(),
88            });
89        }
90        Ok(value)
91    }
92}
93
94impl<'m> MaterialView<'m> {
95    /// Iterates every `IfcMaterialLayerSetUsage` instance in the model.
96    pub fn layer_set_usages(self) -> impl Iterator<Item = MaterialLayerSetUsage<'m>> + 'm {
97        let release = self.release();
98        self.model()
99            .of_type("IFCMATERIALLAYERSETUSAGE")
100            .map(move |(id, entity)| MaterialLayerSetUsage::from_known(id, entity, release))
101    }
102}