ifc_material/profile/
usage.rs1use ifc_model::EntityId;
4
5use crate::view::{borrowed_entity, optional_integer, optional_number, required_ref, MaterialView};
6use crate::{CardinalPointReference, MaterialError, MaterialResult};
7
8borrowed_entity!(MaterialProfileSetUsage, "IFCMATERIALPROFILESETUSAGE");
9borrowed_entity!(
10 MaterialProfileSetUsageTapering,
11 "IFCMATERIALPROFILESETUSAGETAPERING"
12);
13
14fn cardinal(
15 entity_type: &'static str,
16 id: EntityId,
17 entity: &ifc_model::Entity,
18 slot: usize,
19 attribute: &'static str,
20) -> MaterialResult<Option<CardinalPointReference>> {
21 let Some(value) = optional_integer(entity_type, id, entity, slot, attribute)? else {
22 return Ok(None);
23 };
24 CardinalPointReference::new(value)
25 .map(Some)
26 .ok_or_else(|| MaterialError::InvalidValue {
27 entity: entity_type,
28 id,
29 attribute,
30 value: value.to_string(),
31 })
32}
33
34fn positive_extent(
35 entity_type: &'static str,
36 id: EntityId,
37 entity: &ifc_model::Entity,
38 slot: usize,
39) -> MaterialResult<Option<f64>> {
40 let value = optional_number(entity_type, id, entity, slot, "ReferenceExtent")?;
41 if value.is_some_and(|value| value <= 0.0) {
42 return Err(MaterialError::InvalidValue {
43 entity: entity_type,
44 id,
45 attribute: "ReferenceExtent",
46 value: "expected a positive length".to_owned(),
47 });
48 }
49 Ok(value)
50}
51
52macro_rules! usage_accessors {
53 ($type:ident, $ifc_name:literal) => {
54 impl $type<'_> {
55 pub fn profile_set_id(self) -> MaterialResult<EntityId> {
57 required_ref(
58 $ifc_name,
59 self.id(),
60 self.entity(),
61 self.slot("ForProfileSet")?,
62 "ForProfileSet",
63 )
64 }
65
66 pub fn cardinal_point(self) -> MaterialResult<Option<CardinalPointReference>> {
69 cardinal(
70 $ifc_name,
71 self.id(),
72 self.entity(),
73 self.slot("CardinalPoint")?,
74 "CardinalPoint",
75 )
76 }
77
78 pub fn reference_extent(self) -> MaterialResult<Option<f64>> {
81 positive_extent(
82 $ifc_name,
83 self.id(),
84 self.entity(),
85 self.slot("ReferenceExtent")?,
86 )
87 }
88 }
89 };
90}
91usage_accessors!(MaterialProfileSetUsage, "IFCMATERIALPROFILESETUSAGE");
92usage_accessors!(
93 MaterialProfileSetUsageTapering,
94 "IFCMATERIALPROFILESETUSAGETAPERING"
95);
96
97impl MaterialProfileSetUsageTapering<'_> {
98 pub fn end_profile_set_id(self) -> MaterialResult<EntityId> {
100 required_ref(
101 "IFCMATERIALPROFILESETUSAGETAPERING",
102 self.id(),
103 self.entity(),
104 self.slot("ForProfileEndSet")?,
105 "ForProfileEndSet",
106 )
107 }
108
109 pub fn cardinal_end_point(self) -> MaterialResult<Option<CardinalPointReference>> {
112 cardinal(
113 "IFCMATERIALPROFILESETUSAGETAPERING",
114 self.id(),
115 self.entity(),
116 self.slot("CardinalEndPoint")?,
117 "CardinalEndPoint",
118 )
119 }
120}
121
122impl<'m> MaterialView<'m> {
123 pub fn profile_set_usages(self) -> impl Iterator<Item = MaterialProfileSetUsage<'m>> + 'm {
125 let release = self.release();
126 self.model()
127 .of_type("IFCMATERIALPROFILESETUSAGE")
128 .map(move |(id, entity)| MaterialProfileSetUsage::from_known(id, entity, release))
129 }
130
131 pub fn tapering_profile_set_usages(
134 self,
135 ) -> impl Iterator<Item = MaterialProfileSetUsageTapering<'m>> + 'm {
136 let release = self.release();
137 self.model()
138 .of_type("IFCMATERIALPROFILESETUSAGETAPERING")
139 .map(move |(id, entity)| {
140 MaterialProfileSetUsageTapering::from_known(id, entity, release)
141 })
142 }
143}