use super::*;
use ifc_lite_core::EntityDecoder;
const SELF_BASIS: &str = r#"ISO-10303-21;
HEADER;
FILE_DESCRIPTION((''),'2;1');
FILE_NAME('t.ifc','2024-01-01T00:00:00',(''),(''),'','','');
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#10=IFCTRIMMEDCURVE(#10,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.);
ENDSEC;
END-ISO-10303-21;
"#;
const TWO_CYCLE: &str = r#"ISO-10303-21;
HEADER;
FILE_DESCRIPTION((''),'2;1');
FILE_NAME('t.ifc','2024-01-01T00:00:00',(''),(''),'','','');
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#10=IFCTRIMMEDCURVE(#11,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.);
#11=IFCTRIMMEDCURVE(#10,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.);
ENDSEC;
END-ISO-10303-21;
"#;
const NESTED_TRIM_ON_LINE: &str = r#"ISO-10303-21;
HEADER;
FILE_DESCRIPTION((''),'2;1');
FILE_NAME('t.ifc','2024-01-01T00:00:00',(''),(''),'','','');
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#10=IFCTRIMMEDCURVE(#11,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.);
#11=IFCTRIMMEDCURVE(#12,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.);
#12=IFCLINE(#13,#14);
#13=IFCCARTESIANPOINT((0.,0.,0.));
#14=IFCVECTOR(#15,1.);
#15=IFCDIRECTION((1.,0.,0.));
ENDSEC;
END-ISO-10303-21;
"#;
fn wrap(data: &str) -> String {
format!(
"ISO-10303-21;\nHEADER;\nFILE_DESCRIPTION((''),'2;1');\n\
FILE_NAME('t.ifc','2024-01-01T00:00:00',(''),(''),'','','');\n\
FILE_SCHEMA(('IFC4'));\nENDSEC;\nDATA;\n{data}ENDSEC;\nEND-ISO-10303-21;\n"
)
}
fn sample(content: &str, id: u32) -> Vec<Point3<f64>> {
let mut decoder = EntityDecoder::new(content);
let curve = decoder.decode_by_id(id).expect("decode curve");
sample_curve_polyline(&curve, &mut decoder, TessellationQuality::default())
}
#[test]
fn self_referential_basis_curve_terminates() {
assert!(sample(SELF_BASIS, 10).is_empty());
}
#[test]
fn two_node_basis_curve_cycle_terminates() {
assert!(sample(TWO_CYCLE, 10).is_empty());
}
#[test]
fn a_legitimate_nested_trim_still_samples() {
let pts = sample(NESTED_TRIM_ON_LINE, 10);
assert!(
pts.len() >= 2,
"nested-but-acyclic trimming must still yield a polyline, got {} points",
pts.len()
);
}
#[test]
fn a_long_acyclic_basis_chain_terminates() {
let n: u32 = 5_000;
let mut data = String::new();
for i in 1..n {
data.push_str(&format!(
"#{}=IFCTRIMMEDCURVE(#{},(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.);\n",
i,
i + 1
));
}
data.push_str(&format!("#{n}=IFCCARTESIANPOINT((0.,0.,0.));\n"));
assert!(sample(&wrap(&data), 1).is_empty());
}