use crate::error::GeometryResult;
use crate::slots::Slots;
use ifc_model::{Entity, EntityId};
pub(crate) mod slot {
pub const SBSM_BOUNDARY: usize = 0;
pub const FBSM_FACES: usize = 0;
pub const ELEMENTS: usize = 0;
}
#[derive(Debug, Clone, Copy)]
pub struct ShellBasedSurfaceModel<'m> {
slots: Slots<'m>,
}
impl<'m> ShellBasedSurfaceModel<'m> {
pub fn new(id: EntityId, entity: &'m Entity) -> Self {
Self {
slots: Slots::new(id, entity),
}
}
pub fn id(&self) -> EntityId {
self.slots.id()
}
pub fn shells(&self) -> GeometryResult<Vec<EntityId>> {
self.slots.req_ref_list(slot::SBSM_BOUNDARY, "SbsmBoundary")
}
}
#[derive(Debug, Clone, Copy)]
pub struct FaceBasedSurfaceModel<'m> {
slots: Slots<'m>,
}
impl<'m> FaceBasedSurfaceModel<'m> {
pub fn new(id: EntityId, entity: &'m Entity) -> Self {
Self {
slots: Slots::new(id, entity),
}
}
pub fn id(&self) -> EntityId {
self.slots.id()
}
pub fn face_sets(&self) -> GeometryResult<Vec<EntityId>> {
self.slots.req_ref_list(slot::FBSM_FACES, "FbsmFaces")
}
}
#[derive(Debug, Clone, Copy)]
pub struct GeometricSet<'m> {
slots: Slots<'m>,
}
impl<'m> GeometricSet<'m> {
pub fn new(id: EntityId, entity: &'m Entity) -> Self {
Self {
slots: Slots::new(id, entity),
}
}
pub fn id(&self) -> EntityId {
self.slots.id()
}
pub fn type_name(&self) -> &'m str {
self.slots.type_name()
}
pub fn elements(&self) -> GeometryResult<Vec<EntityId>> {
self.slots.req_ref_list(slot::ELEMENTS, "Elements")
}
pub fn is_curve_set(&self) -> bool {
self.type_name()
.eq_ignore_ascii_case("IFCGEOMETRICCURVESET")
}
}
#[derive(Debug, Clone, Copy)]
pub struct GeometricCurveSet<'m> {
slots: Slots<'m>,
}
impl<'m> GeometricCurveSet<'m> {
pub fn new(id: EntityId, entity: &'m Entity) -> Self {
Self {
slots: Slots::new(id, entity),
}
}
pub fn id(&self) -> EntityId {
self.slots.id()
}
pub fn base(&self) -> GeometricSet<'m> {
GeometricSet { slots: self.slots }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::solid::testkit::{entity, refs};
#[test]
fn shell_based_surface_model_exposes_shells_without_claiming_a_solid() {
let e = entity("IFCSHELLBASEDSURFACEMODEL", vec![refs(&[10, 11])]);
let view = ShellBasedSurfaceModel::new(EntityId(1), &e);
assert_eq!(view.shells().unwrap(), vec![EntityId(10), EntityId(11)]);
}
#[test]
fn face_based_surface_model_exposes_its_connected_face_sets() {
let e = entity("IFCFACEBASEDSURFACEMODEL", vec![refs(&[20, 21, 22])]);
let view = FaceBasedSurfaceModel::new(EntityId(1), &e);
assert_eq!(
view.face_sets().unwrap(),
vec![EntityId(20), EntityId(21), EntityId(22)]
);
}
#[test]
fn geometric_set_elements_are_returned_unresolved_and_in_order() {
let e = entity("IFCGEOMETRICSET", vec![refs(&[30, 31, 32])]);
let view = GeometricSet::new(EntityId(1), &e);
assert_eq!(
view.elements().unwrap(),
vec![EntityId(30), EntityId(31), EntityId(32)]
);
assert!(!view.is_curve_set());
}
#[test]
fn curve_set_inherits_elements_at_the_same_slot() {
let e = entity("IFCGEOMETRICCURVESET", vec![refs(&[40, 41])]);
let view = GeometricCurveSet::new(EntityId(1), &e);
assert_eq!(
view.base().elements().unwrap(),
vec![EntityId(40), EntityId(41)]
);
assert!(view.base().is_curve_set());
}
#[test]
fn an_empty_collection_slot_reports_the_missing_attribute() {
let e = entity("IFCSHELLBASEDSURFACEMODEL", vec![]);
let err = ShellBasedSurfaceModel::new(EntityId(5), &e)
.shells()
.unwrap_err();
assert_eq!(err.entity(), Some(EntityId(5)));
assert!(err.to_string().contains("SbsmBoundary"));
}
}