use ifc_model::{EntityId, Model, Transaction, Value};
use crate::PropertyResult;
use super::owned::{stage_ifc4, stage_owned, Rooted};
use super::predefined::{invalid, measure, ratio, require_guid, Measure};
#[derive(Debug, Clone, Copy, Default)]
pub struct DoorLiningDraft<'a> {
pub name: Option<&'a str>,
pub description: Option<&'a str>,
pub lining_depth: Option<f64>,
pub lining_thickness: Option<f64>,
pub threshold_depth: Option<f64>,
pub threshold_thickness: Option<f64>,
pub transom_thickness: Option<f64>,
pub transom_offset: Option<f64>,
pub lining_offset: Option<f64>,
pub threshold_offset: Option<f64>,
pub casing_thickness: Option<f64>,
pub casing_depth: Option<f64>,
pub shape_aspect_style: Option<EntityId>,
pub lining_to_panel_offset_x: Option<f64>,
pub lining_to_panel_offset_y: Option<f64>,
}
pub fn add_door_lining_properties(
tx: &mut Transaction,
global_id: &str,
draft: DoorLiningDraft<'_>,
) -> PropertyResult<EntityId> {
stage_ifc4(tx, door_lining(global_id, draft)?)
}
pub fn add_door_lining_properties_with_owner_history(
tx: &mut Transaction,
model: &Model,
global_id: &str,
draft: DoorLiningDraft<'_>,
owner_history: EntityId,
) -> PropertyResult<EntityId> {
stage_owned(tx, model, door_lining(global_id, draft)?, owner_history)
}
fn door_lining<'a>(global_id: &'a str, draft: DoorLiningDraft<'a>) -> PropertyResult<Rooted<'a>> {
const ENTITY: &str = "IFCDOORLININGPROPERTIES";
if draft.lining_depth.is_some() && draft.lining_thickness.is_none() {
return Err(invalid(
ENTITY,
"LiningThickness",
"WR31: a lining depth needs its thickness",
));
}
if draft.threshold_depth.is_some() && draft.threshold_thickness.is_none() {
return Err(invalid(
ENTITY,
"ThresholdThickness",
"WR32: a threshold depth needs its thickness",
));
}
if draft.transom_offset.is_some() != draft.transom_thickness.is_some() {
return Err(invalid(
ENTITY,
"TransomOffset",
"WR33: transom offset and thickness are all or nothing",
));
}
if draft.casing_depth.is_some() != draft.casing_thickness.is_some() {
return Err(invalid(
ENTITY,
"CasingDepth",
"WR34: casing depth and thickness are all or nothing",
));
}
require_guid(ENTITY, global_id)?;
let m = |attribute, value, kind| measure(ENTITY, attribute, value, kind);
let values = vec![
(
"LiningDepth",
m("LiningDepth", draft.lining_depth, Measure::Positive)?,
),
(
"LiningThickness",
m(
"LiningThickness",
draft.lining_thickness,
Measure::NonNegative,
)?,
),
(
"ThresholdDepth",
m("ThresholdDepth", draft.threshold_depth, Measure::Positive)?,
),
(
"ThresholdThickness",
m(
"ThresholdThickness",
draft.threshold_thickness,
Measure::NonNegative,
)?,
),
(
"TransomThickness",
m(
"TransomThickness",
draft.transom_thickness,
Measure::NonNegative,
)?,
),
(
"TransomOffset",
m("TransomOffset", draft.transom_offset, Measure::Length)?,
),
(
"LiningOffset",
m("LiningOffset", draft.lining_offset, Measure::Length)?,
),
(
"ThresholdOffset",
m("ThresholdOffset", draft.threshold_offset, Measure::Length)?,
),
(
"CasingThickness",
m("CasingThickness", draft.casing_thickness, Measure::Positive)?,
),
(
"CasingDepth",
m("CasingDepth", draft.casing_depth, Measure::Positive)?,
),
(
"ShapeAspectStyle",
draft.shape_aspect_style.map_or(Value::Null, Value::Ref),
),
(
"LiningToPanelOffsetX",
m(
"LiningToPanelOffsetX",
draft.lining_to_panel_offset_x,
Measure::Length,
)?,
),
(
"LiningToPanelOffsetY",
m(
"LiningToPanelOffsetY",
draft.lining_to_panel_offset_y,
Measure::Length,
)?,
),
];
Ok(Rooted {
entity: ENTITY,
global_id,
name: draft.name,
description: draft.description,
values,
})
}
#[derive(Debug, Clone, Copy, Default)]
pub struct WindowLiningDraft<'a> {
pub name: Option<&'a str>,
pub description: Option<&'a str>,
pub lining_depth: Option<f64>,
pub lining_thickness: Option<f64>,
pub transom_thickness: Option<f64>,
pub mullion_thickness: Option<f64>,
pub first_transom_offset: Option<f64>,
pub second_transom_offset: Option<f64>,
pub first_mullion_offset: Option<f64>,
pub second_mullion_offset: Option<f64>,
pub shape_aspect_style: Option<EntityId>,
pub lining_offset: Option<f64>,
pub lining_to_panel_offset_x: Option<f64>,
pub lining_to_panel_offset_y: Option<f64>,
}
pub fn add_window_lining_properties(
tx: &mut Transaction,
global_id: &str,
draft: WindowLiningDraft<'_>,
) -> PropertyResult<EntityId> {
stage_ifc4(tx, window_lining(global_id, draft)?)
}
pub fn add_window_lining_properties_with_owner_history(
tx: &mut Transaction,
model: &Model,
global_id: &str,
draft: WindowLiningDraft<'_>,
owner_history: EntityId,
) -> PropertyResult<EntityId> {
stage_owned(tx, model, window_lining(global_id, draft)?, owner_history)
}
fn window_lining<'a>(
global_id: &'a str,
draft: WindowLiningDraft<'a>,
) -> PropertyResult<Rooted<'a>> {
const ENTITY: &str = "IFCWINDOWLININGPROPERTIES";
if draft.lining_depth.is_some() && draft.lining_thickness.is_none() {
return Err(invalid(
ENTITY,
"LiningThickness",
"WR31: a lining depth needs its thickness",
));
}
if draft.second_transom_offset.is_some() && draft.first_transom_offset.is_none() {
return Err(invalid(
ENTITY,
"SecondTransomOffset",
"WR32: a second transom offset needs the first",
));
}
if draft.second_mullion_offset.is_some() && draft.first_mullion_offset.is_none() {
return Err(invalid(
ENTITY,
"SecondMullionOffset",
"WR33: a second mullion offset needs the first",
));
}
require_guid(ENTITY, global_id)?;
let m = |attribute, value, kind| measure(ENTITY, attribute, value, kind);
let r = |attribute, value| ratio(ENTITY, attribute, value);
let values = vec![
(
"LiningDepth",
m("LiningDepth", draft.lining_depth, Measure::Positive)?,
),
(
"LiningThickness",
m(
"LiningThickness",
draft.lining_thickness,
Measure::NonNegative,
)?,
),
(
"TransomThickness",
m(
"TransomThickness",
draft.transom_thickness,
Measure::NonNegative,
)?,
),
(
"MullionThickness",
m(
"MullionThickness",
draft.mullion_thickness,
Measure::NonNegative,
)?,
),
(
"FirstTransomOffset",
r("FirstTransomOffset", draft.first_transom_offset)?,
),
(
"SecondTransomOffset",
r("SecondTransomOffset", draft.second_transom_offset)?,
),
(
"FirstMullionOffset",
r("FirstMullionOffset", draft.first_mullion_offset)?,
),
(
"SecondMullionOffset",
r("SecondMullionOffset", draft.second_mullion_offset)?,
),
(
"ShapeAspectStyle",
draft.shape_aspect_style.map_or(Value::Null, Value::Ref),
),
(
"LiningOffset",
m("LiningOffset", draft.lining_offset, Measure::Length)?,
),
(
"LiningToPanelOffsetX",
m(
"LiningToPanelOffsetX",
draft.lining_to_panel_offset_x,
Measure::Length,
)?,
),
(
"LiningToPanelOffsetY",
m(
"LiningToPanelOffsetY",
draft.lining_to_panel_offset_y,
Measure::Length,
)?,
),
];
Ok(Rooted {
entity: ENTITY,
global_id,
name: draft.name,
description: draft.description,
values,
})
}