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) -> MaterialResult<Option<f64>> {
39 let value = optional_number(entity_type, id, entity, 2, "ReferenceExtent")?;
40 if value.is_some_and(|value| value <= 0.0) {
41 return Err(MaterialError::InvalidValue {
42 entity: entity_type,
43 id,
44 attribute: "ReferenceExtent",
45 value: "expected a positive length".to_owned(),
46 });
47 }
48 Ok(value)
49}
50
51macro_rules! usage_accessors {
52 ($type:ident, $ifc_name:literal) => {
53 impl $type<'_> {
54 pub fn profile_set_id(self) -> MaterialResult<EntityId> {
56 required_ref($ifc_name, self.id(), self.entity(), 0, "ForProfileSet")
57 }
58
59 pub fn cardinal_point(self) -> MaterialResult<Option<CardinalPointReference>> {
62 cardinal($ifc_name, self.id(), self.entity(), 1, "CardinalPoint")
63 }
64
65 pub fn reference_extent(self) -> MaterialResult<Option<f64>> {
68 positive_extent($ifc_name, self.id(), self.entity())
69 }
70 }
71 };
72}
73usage_accessors!(MaterialProfileSetUsage, "IFCMATERIALPROFILESETUSAGE");
74usage_accessors!(
75 MaterialProfileSetUsageTapering,
76 "IFCMATERIALPROFILESETUSAGETAPERING"
77);
78
79impl MaterialProfileSetUsageTapering<'_> {
80 pub fn end_profile_set_id(self) -> MaterialResult<EntityId> {
82 required_ref(
83 "IFCMATERIALPROFILESETUSAGETAPERING",
84 self.id(),
85 self.entity(),
86 3,
87 "ForProfileEndSet",
88 )
89 }
90
91 pub fn cardinal_end_point(self) -> MaterialResult<Option<CardinalPointReference>> {
94 cardinal(
95 "IFCMATERIALPROFILESETUSAGETAPERING",
96 self.id(),
97 self.entity(),
98 4,
99 "CardinalEndPoint",
100 )
101 }
102}
103
104impl<'m> MaterialView<'m> {
105 pub fn profile_set_usages(self) -> impl Iterator<Item = MaterialProfileSetUsage<'m>> + 'm {
107 self.model()
108 .of_type("IFCMATERIALPROFILESETUSAGE")
109 .map(|(id, entity)| MaterialProfileSetUsage::from_known(id, entity))
110 }
111
112 pub fn tapering_profile_set_usages(
115 self,
116 ) -> impl Iterator<Item = MaterialProfileSetUsageTapering<'m>> + 'm {
117 self.model()
118 .of_type("IFCMATERIALPROFILESETUSAGETAPERING")
119 .map(|(id, entity)| MaterialProfileSetUsageTapering::from_known(id, entity))
120 }
121}