Skip to main content

ifc_style/layer/
assignment.rs

1//! Presentation layer membership and layer-level styles.
2
3use ifc_model::EntityId;
4use ifc_schema::SchemaVersion;
5
6use crate::assignment::{presentation_style_members, PresentationStyleMember};
7use crate::error::StyleResult;
8use crate::view::Record;
9
10/// Borrowed projection of `IfcPresentationLayerAssignment` (and its
11/// `IfcPresentationLayerWithStyle` subtype).
12#[derive(Debug, Clone, Copy)]
13pub struct PresentationLayer<'m, 's> {
14    pub(crate) record: Record<'m, 's>,
15}
16
17impl<'m, 's> PresentationLayer<'m, 's> {
18    pub(crate) fn from_record(record: Record<'m, 's>) -> Self {
19        Self { record }
20    }
21
22    /// The entity id of this layer assignment.
23    pub fn id(&self) -> EntityId {
24        self.record.id
25    }
26
27    /// The `Name` attribute. Mandatory.
28    pub fn name(&self) -> StyleResult<&'m str> {
29        self.record.required_text("Name")
30    }
31
32    /// The `Description` attribute, when authored.
33    pub fn description(&self) -> StyleResult<Option<&'m str>> {
34        self.record.optional_text("Description")
35    }
36
37    /// The `Identifier` attribute, when authored.
38    pub fn identifier(&self) -> StyleResult<Option<&'m str>> {
39        self.record.optional_text("Identifier")
40    }
41
42    /// The `AssignedItems` select: the `IfcRepresentation`s and/or
43    /// `IfcRepresentationItem`s placed on this layer.
44    pub fn assigned_items(&self) -> StyleResult<Vec<EntityId>> {
45        self.record.required_refs_select(
46            "AssignedItems",
47            "IfcLayeredItem",
48            &["IfcRepresentation", "IfcRepresentationItem"],
49            1,
50            None,
51        )
52    }
53
54    /// The `LayerStyles` attribute of an `IfcPresentationLayerWithStyle`.
55    /// Returns an empty vector when the entity has no `LayerStyles` slot at
56    /// all (a plain `IfcPresentationLayerAssignment`). On IFC2x3, resolves
57    /// through the legacy `IfcPresentationStyleAssignment` select and drops
58    /// `IfcNullStyle.NULL` members; on later schemas, reads direct
59    /// `IfcPresentationStyle` references.
60    pub fn layer_styles(&self) -> StyleResult<Vec<EntityId>> {
61        if !self.record.has_attribute("LayerStyles") {
62            return Ok(Vec::new());
63        }
64        if self.record.schema.version() == Some(SchemaVersion::Ifc2x3) {
65            return Ok(presentation_style_members(self.record, "LayerStyles", 0)?
66                .into_iter()
67                .filter_map(|member| match member {
68                    PresentationStyleMember::Style(id) => Some(id),
69                    PresentationStyleMember::Null => None,
70                })
71                .collect());
72        }
73        self.record
74            .required_refs("LayerStyles", "IfcPresentationStyle", 0, None)
75    }
76}