use ifc_model::{Entity, EntityId, Transaction, Value};
use crate::error::GeometryError;
use crate::resource::direction::slot as direction_slot;
use crate::resource::placement::slot as placement_slot;
use crate::resource::point::slot as point_slot;
use super::{invalid, reals, require_finite};
pub fn cartesian_point(tx: &mut Transaction, coords: &[f64]) -> Result<EntityId, GeometryError> {
if coords.is_empty() || coords.len() > 3 {
return Err(invalid(
"IFCCARTESIANPOINT",
"Coordinates",
format!("expected 1..=3 coordinates, got {}", coords.len()),
));
}
require_finite("IFCCARTESIANPOINT", "Coordinates", coords)?;
let mut attrs = vec![Value::Null];
attrs[point_slot::cartesian_point::COORDINATES] = reals(coords);
Ok(tx.create(Entity::new("IFCCARTESIANPOINT", attrs)))
}
pub fn direction(tx: &mut Transaction, ratios: &[f64]) -> Result<EntityId, GeometryError> {
if ratios.len() < 2 || ratios.len() > 3 {
return Err(invalid(
"IFCDIRECTION",
"DirectionRatios",
format!("expected 2..=3 ratios, got {}", ratios.len()),
));
}
require_finite("IFCDIRECTION", "DirectionRatios", ratios)?;
if ratios.iter().all(|r| *r == 0.0) {
return Err(invalid(
"IFCDIRECTION",
"DirectionRatios",
"all ratios are zero, which denotes no direction",
));
}
let mut attrs = vec![Value::Null];
attrs[direction_slot::direction::DIRECTION_RATIOS] = reals(ratios);
Ok(tx.create(Entity::new("IFCDIRECTION", attrs)))
}
pub fn axis2_placement_3d(
tx: &mut Transaction,
location: EntityId,
axis: Option<EntityId>,
ref_direction: Option<EntityId>,
) -> EntityId {
let mut attrs = vec![Value::Null, Value::Null, Value::Null];
attrs[placement_slot::LOCATION] = Value::Ref(location);
attrs[placement_slot::axis2_3d::AXIS] = axis.map_or(Value::Null, Value::Ref);
attrs[placement_slot::axis2_3d::REF_DIRECTION] = ref_direction.map_or(Value::Null, Value::Ref);
tx.create(Entity::new("IFCAXIS2PLACEMENT3D", attrs))
}
pub fn axis2_placement_2d(
tx: &mut Transaction,
location: EntityId,
ref_direction: Option<EntityId>,
) -> EntityId {
let mut attrs = vec![Value::Null, Value::Null];
attrs[placement_slot::LOCATION] = Value::Ref(location);
attrs[placement_slot::axis2_2d::REF_DIRECTION] = ref_direction.map_or(Value::Null, Value::Ref);
tx.create(Entity::new("IFCAXIS2PLACEMENT2D", attrs))
}