#![cfg(feature = "lowering")]
use axiolid_model::{GeometryNode, SurfaceRelation};
use axiolid_surface::Surface;
use ifc_geometry::lower::{lower_representation_item, lower_surface_node, LoweringSession};
use ifc_geometry::transform::Transform;
use ifc_geometry::units;
use ifc_model::{Codec, Model};
use ifc_step::StepCodec;
use std::path::PathBuf;
const DUCT: &str = "ifclite-geometry/issue_1485_duct_elbow_surface_curve_swept.ifc";
fn fixture(name: &str) -> Model {
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../test/fixtures")
.join(name);
StepCodec
.read_path(&path)
.unwrap_or_else(|e| panic!("fixture {} must parse: {e:?}", path.display()))
}
#[test]
fn the_duct_elbow_reference_surface_lowers_through_its_open_generatrix() {
let model = fixture(DUCT);
let scale = units::resolve(&model);
let ids = model.ids_of_type("IFCSURFACEOFLINEAREXTRUSION");
assert_eq!(ids.len(), 1, "the fixture carries one extruded surface");
let mut session = LoweringSession::new(&model, &scale);
let node = lower_surface_node(&mut session, ids[0], Transform::identity())
.expect("the reference surface must lower");
let lowered = session.finish(node).expect("session finishes");
assert!(
matches!(
lowered.graph.get(lowered.root),
Some(GeometryNode::SurfaceRelation(
SurfaceRelation::LinearExtrusion { .. }
))
),
"expected a linear extrusion at the root"
);
}
#[test]
fn the_duct_elbow_swept_solid_lowers_end_to_end() {
let model = fixture(DUCT);
let scale = units::resolve(&model);
let ids = model.ids_of_type("IFCSURFACECURVESWEPTAREASOLID");
assert_eq!(ids.len(), 1, "the fixture carries one surface-curve sweep");
let mut session = LoweringSession::new(&model, &scale);
lower_representation_item(&mut session, ids[0], Transform::identity())
.expect("the sweep must lower now that its generatrix resolves");
}
#[test]
fn every_corpus_plane_lowers_to_an_orthonormal_frame() {
let mut seen = 0usize;
for name in [
"ifclite-geometry/issue_1155_halfspace_flyaway.ifc",
"synthetic-surfaces/synthetic_curve_bounded_plane.ifc",
] {
let model = fixture(name);
let scale = units::resolve(&model);
for id in model.ids_of_type("IFCPLANE") {
let mut session = LoweringSession::new(&model, &scale);
let node = lower_surface_node(&mut session, *id, Transform::identity())
.expect("a plane must lower");
let lowered = session.finish(node).expect("session finishes");
let Some(GeometryNode::Surface(Surface::Plane(plane))) =
lowered.graph.get(lowered.root)
else {
panic!("expected a plane node");
};
for axis in [plane.frame.x, plane.frame.y, plane.frame.z] {
let a = axis.to_array();
let len = (a[0] * a[0] + a[1] * a[1] + a[2] * a[2]).sqrt();
assert!((len - 1.0).abs() < 1e-9, "axis must be unit, got {len}");
}
seen += 1;
}
}
assert!(seen >= 2, "expected planes in both fixtures, saw {seen}");
}