use ifc_model::{Entity, EntityId, Transaction, Value};
use crate::error::GeometryError;
use crate::solid::boolean::{slot as boolean_slot, IfcBooleanOperator};
use crate::solid::swept::{extruded_slot, revolved_slot, swept_area_slot};
use super::invalid;
pub fn extruded_area_solid(
tx: &mut Transaction,
swept_area: EntityId,
position: Option<EntityId>,
extruded_direction: EntityId,
depth: f64,
) -> Result<EntityId, GeometryError> {
if !depth.is_finite() || depth <= 0.0 {
return Err(invalid(
"IFCEXTRUDEDAREASOLID",
"Depth",
format!("expected a positive length, got {depth}"),
));
}
let mut attrs = vec![Value::Null; 4];
attrs[swept_area_slot::SWEPT_AREA] = Value::Ref(swept_area);
attrs[swept_area_slot::POSITION] = position.map_or(Value::Null, Value::Ref);
attrs[extruded_slot::EXTRUDED_DIRECTION] = Value::Ref(extruded_direction);
attrs[extruded_slot::DEPTH] = Value::Real(depth);
Ok(tx.create(Entity::new("IFCEXTRUDEDAREASOLID", attrs)))
}
pub fn revolved_area_solid(
tx: &mut Transaction,
swept_area: EntityId,
position: Option<EntityId>,
axis: EntityId,
angle: f64,
) -> Result<EntityId, GeometryError> {
if !angle.is_finite() || angle <= 0.0 || angle > std::f64::consts::TAU {
return Err(invalid(
"IFCREVOLVEDAREASOLID",
"Angle",
format!("expected an angle in (0, 2pi] radians, got {angle}"),
));
}
let mut attrs = vec![Value::Null; 4];
attrs[swept_area_slot::SWEPT_AREA] = Value::Ref(swept_area);
attrs[swept_area_slot::POSITION] = position.map_or(Value::Null, Value::Ref);
attrs[revolved_slot::AXIS] = Value::Ref(axis);
attrs[revolved_slot::ANGLE] = Value::Real(angle);
Ok(tx.create(Entity::new("IFCREVOLVEDAREASOLID", attrs)))
}
pub fn boolean_result(
tx: &mut Transaction,
operator: IfcBooleanOperator,
first: EntityId,
second: EntityId,
) -> Result<EntityId, GeometryError> {
if first == second {
return Err(invalid(
"IFCBOOLEANRESULT",
"SecondOperand",
"both operands are the same entity",
));
}
let mut attrs = vec![Value::Null; 3];
attrs[boolean_slot::OPERATOR] = Value::Enum(operator.as_token().into());
attrs[boolean_slot::FIRST_OPERAND] = Value::Ref(first);
attrs[boolean_slot::SECOND_OPERAND] = Value::Ref(second);
Ok(tx.create(Entity::new("IFCBOOLEANRESULT", attrs)))
}