use ifc_model::{Entity, EntityId, Transaction, Value};
use super::{finite, guid, invalid};
use crate::error::AlignmentError;
use crate::slot;
fn product_attrs(
type_name: &'static str,
arity: usize,
global_id: &str,
name: Option<&str>,
) -> Result<Vec<Value>, AlignmentError> {
let mut attrs = vec![Value::Null; arity];
attrs[slot::product::GLOBAL_ID] = guid(type_name, global_id)?;
if let Some(name) = name {
attrs[slot::product::NAME] = Value::Text(name.into());
}
Ok(attrs)
}
pub fn alignment(
tx: &mut Transaction,
global_id: &str,
name: Option<&str>,
predefined_type: Option<&'static str>,
) -> Result<EntityId, AlignmentError> {
let mut attrs = product_attrs("IFCALIGNMENT", slot::alignment::ARITY, global_id, name)?;
if let Some(token) = predefined_type {
attrs[slot::alignment::PREDEFINED_TYPE] = Value::Enum(token.into());
}
Ok(tx.create(Entity::new("IFCALIGNMENT", attrs)))
}
pub fn horizontal_layout(
tx: &mut Transaction,
global_id: &str,
name: Option<&str>,
) -> Result<EntityId, AlignmentError> {
let attrs = product_attrs(
"IFCALIGNMENTHORIZONTAL",
slot::product::ARITY,
global_id,
name,
)?;
Ok(tx.create(Entity::new("IFCALIGNMENTHORIZONTAL", attrs)))
}
pub fn vertical_layout(
tx: &mut Transaction,
global_id: &str,
name: Option<&str>,
) -> Result<EntityId, AlignmentError> {
let attrs = product_attrs(
"IFCALIGNMENTVERTICAL",
slot::product::ARITY,
global_id,
name,
)?;
Ok(tx.create(Entity::new("IFCALIGNMENTVERTICAL", attrs)))
}
pub fn cant_layout(
tx: &mut Transaction,
global_id: &str,
name: Option<&str>,
rail_head_distance: f64,
) -> Result<EntityId, AlignmentError> {
finite("IFCALIGNMENTCANT", "RailHeadDistance", rail_head_distance)?;
if rail_head_distance <= 0.0 {
return Err(invalid(
"IFCALIGNMENTCANT",
"RailHeadDistance",
"the distance between rail heads must be positive",
));
}
let mut attrs = product_attrs(
"IFCALIGNMENTCANT",
slot::cant_layout::ARITY,
global_id,
name,
)?;
attrs[slot::cant_layout::RAIL_HEAD_DISTANCE] = Value::Real(rail_head_distance);
Ok(tx.create(Entity::new("IFCALIGNMENTCANT", attrs)))
}
pub fn alignment_segment(
tx: &mut Transaction,
global_id: &str,
design_parameters: EntityId,
) -> Result<EntityId, AlignmentError> {
let mut attrs = product_attrs("IFCALIGNMENTSEGMENT", slot::segment::ARITY, global_id, None)?;
attrs[slot::segment::DESIGN_PARAMETERS] = Value::Ref(design_parameters);
Ok(tx.create(Entity::new("IFCALIGNMENTSEGMENT", attrs)))
}