use super::items::extract_symbolic_item_inner;
use super::primitives::SymbolicData;
use super::transform::Transform2D;
use ifc_lite_core::{DecodedEntity, EntityDecoder};
use rustc_hash::FxHashSet;
use std::collections::HashMap;
pub(super) const MAX_ITEM_DEPTH: u32 = 32;
pub(super) const MAX_ITEM_REVISITS: u32 = 200_000;
pub(super) struct ItemWalk {
path: FxHashSet<u32>,
seen: FxHashSet<u32>,
revisit_budget: u32,
}
impl ItemWalk {
pub(super) fn enter_node(&mut self, id: u32) -> bool {
self.path.insert(id)
}
pub(super) fn exit_node(&mut self, id: u32) {
self.path.remove(&id);
}
}
#[allow(clippy::too_many_arguments)]
pub(super) fn extract_symbolic_item(
item: &DecodedEntity,
decoder: &mut EntityDecoder,
express_id: u32,
ifc_type: &str,
rep_identifier: &str,
unit_scale: f32,
transform: &Transform2D,
rtc_x: f32,
rtc_z: f32,
styled_items: &HashMap<u32, Vec<u32>>,
out: &mut SymbolicData,
) {
let mut walk = ItemWalk {
path: FxHashSet::default(),
seen: FxHashSet::default(),
revisit_budget: MAX_ITEM_REVISITS,
};
extract_symbolic_item_at(
item, decoder, express_id, ifc_type, rep_identifier, unit_scale, transform, rtc_x, rtc_z,
styled_items, out, 0, &mut walk,
);
}
#[cfg(test)]
#[allow(clippy::too_many_arguments)]
pub(super) fn extract_symbolic_item_with_revisit_budget(
item: &DecodedEntity,
decoder: &mut EntityDecoder,
express_id: u32,
ifc_type: &str,
rep_identifier: &str,
unit_scale: f32,
transform: &Transform2D,
rtc_x: f32,
rtc_z: f32,
styled_items: &HashMap<u32, Vec<u32>>,
out: &mut SymbolicData,
revisit_budget: u32,
) {
let mut walk = ItemWalk {
path: FxHashSet::default(),
seen: FxHashSet::default(),
revisit_budget,
};
extract_symbolic_item_at(
item, decoder, express_id, ifc_type, rep_identifier, unit_scale, transform, rtc_x, rtc_z,
styled_items, out, 0, &mut walk,
);
}
#[allow(clippy::too_many_arguments)]
pub(super) fn extract_symbolic_item_at(
item: &DecodedEntity,
decoder: &mut EntityDecoder,
express_id: u32,
ifc_type: &str,
rep_identifier: &str,
unit_scale: f32,
transform: &Transform2D,
rtc_x: f32,
rtc_z: f32,
styled_items: &HashMap<u32, Vec<u32>>,
out: &mut SymbolicData,
depth: u32,
walk: &mut ItemWalk,
) {
if depth >= MAX_ITEM_DEPTH {
return;
}
if !walk.seen.insert(item.id) {
match walk.revisit_budget.checked_sub(1) {
Some(left) => walk.revisit_budget = left,
None => return,
}
}
if !walk.enter_node(item.id) {
return;
}
extract_symbolic_item_inner(
item, decoder, express_id, ifc_type, rep_identifier, unit_scale, transform, rtc_x, rtc_z,
styled_items, out, depth, walk,
);
walk.exit_node(item.id);
}