ifc_spatial/authoring/
external.rs1use ifc_model::guid::Guid;
17use ifc_model::{Entity, EntityId, Transaction, Value};
18
19use super::{invalid, optional_text, SpatialAuthoringResult};
20
21const EXTERNAL_KIND: &[&str] = &[
26 "EXTERNAL",
27 "EXTERNAL_EARTH",
28 "EXTERNAL_FIRE",
29 "EXTERNAL_WATER",
30 "USERDEFINED",
31 "NOTDEFINED",
32];
33
34#[derive(Debug, Clone, Copy, Default)]
36pub struct ExternalSpatialDraft<'a> {
37 pub name: Option<&'a str>,
39 pub description: Option<&'a str>,
41 pub object_type: Option<&'a str>,
43 pub placement: Option<EntityId>,
45 pub representation: Option<EntityId>,
47 pub long_name: Option<&'a str>,
49 pub predefined_type: Option<&'a str>,
51}
52
53pub fn create_external_spatial_element(
61 tx: &mut Transaction,
62 global_id: &str,
63 draft: ExternalSpatialDraft<'_>,
64) -> SpatialAuthoringResult<EntityId> {
65 const ENTITY: &str = "IFCEXTERNALSPATIALELEMENT";
66 if Guid::parse(global_id).is_none() {
67 return Err(invalid(ENTITY, "GlobalId", global_id));
68 }
69 if let Some(token) = draft.predefined_type {
70 if !EXTERNAL_KIND.contains(&token) {
71 return Err(invalid(ENTITY, "PredefinedType", token));
72 }
73 if token == "USERDEFINED"
74 && draft
75 .object_type
76 .is_none_or(|value| value.trim().is_empty())
77 {
78 return Err(invalid(ENTITY, "ObjectType", "required by USERDEFINED"));
79 }
80 }
81 let mut attributes = vec![Value::Null; 9];
82 attributes[0] = Value::Text(global_id.into());
83 attributes[2] = optional_text(draft.name);
84 attributes[3] = optional_text(draft.description);
85 attributes[4] = optional_text(draft.object_type);
86 attributes[5] = draft.placement.map_or(Value::Null, Value::Ref);
87 attributes[6] = draft.representation.map_or(Value::Null, Value::Ref);
88 attributes[7] = optional_text(draft.long_name);
89 attributes[8] = draft
90 .predefined_type
91 .map_or(Value::Null, |t| Value::Enum(t.into()));
92 Ok(tx.create(Entity::new(ENTITY, attributes)))
93}
94
95#[derive(Debug, Clone, Copy, Default)]
97pub struct ProjectLibraryDraft<'a> {
98 pub name: Option<&'a str>,
100 pub description: Option<&'a str>,
102 pub object_type: Option<&'a str>,
104 pub long_name: Option<&'a str>,
106 pub phase: Option<&'a str>,
108 pub units: Option<EntityId>,
110}
111
112pub fn create_project_library(
126 tx: &mut Transaction,
127 global_id: &str,
128 draft: ProjectLibraryDraft<'_>,
129 representation_contexts: &[EntityId],
130) -> SpatialAuthoringResult<EntityId> {
131 const ENTITY: &str = "IFCPROJECTLIBRARY";
132 if Guid::parse(global_id).is_none() {
133 return Err(invalid(ENTITY, "GlobalId", global_id));
134 }
135 let mut attributes = vec![Value::Null; 9];
136 attributes[0] = Value::Text(global_id.into());
137 attributes[2] = optional_text(draft.name);
138 attributes[3] = optional_text(draft.description);
139 attributes[4] = optional_text(draft.object_type);
140 attributes[5] = optional_text(draft.long_name);
141 attributes[6] = optional_text(draft.phase);
142 if !representation_contexts.is_empty() {
143 attributes[7] = Value::List(
144 representation_contexts
145 .iter()
146 .copied()
147 .map(Value::Ref)
148 .collect(),
149 );
150 }
151 attributes[8] = draft.units.map_or(Value::Null, Value::Ref);
152 Ok(tx.create(Entity::new(ENTITY, attributes)))
153}