use cadrum::{Compound, Solid};
use glam::DVec3;
fn dvec3(x: f64, y: f64, z: f64) -> DVec3 {
DVec3::new(x, y, z)
}
fn test_box() -> Solid {
Solid::cube(10.0, 10.0, 10.0)
}
fn test_box_2() -> Solid {
Solid::cube(10.0, 10.0, 10.0).translate(dvec3(5.0, 5.0, 5.0))
}
fn test_box_3() -> Solid {
Solid::cube(5.0, 5.0, 5.0).translate(dvec3(3.0, 3.0, 3.0))
}
fn shape_to_brep_bytes<'a>(shape: impl IntoIterator<Item = &'a Solid>) -> Vec<u8> {
let mut buf = Vec::new();
cadrum::Solid::write_brep_binary(shape, &mut buf).unwrap();
buf
}
#[test]
fn test_t01_union_drop_result_first() {
let a = test_box();
let b = test_box_2();
let result = a.union([&b]).unwrap();
drop(result);
drop(a);
drop(b);
}
#[test]
fn test_t01_union_drop_result_last() {
let a = test_box();
let b = test_box_2();
let result = a.union([&b]).unwrap();
drop(a);
drop(b);
drop(result);
}
#[test]
fn test_t01_subtract_drop_order() {
let a = test_box();
let b = test_box_2();
let result = a.subtract([&b]).unwrap();
drop(a);
drop(b);
drop(result);
}
#[test]
fn test_t01_intersect_drop_order() {
let a = test_box();
let b = test_box_2();
let result = a.intersect([&b]).unwrap();
drop(a);
drop(b);
drop(result);
}
#[test]
fn test_t01_chained_boolean_drops() {
let a = test_box();
let b = test_box_2();
let c = test_box_3();
let r1 = a.union([&b]).unwrap();
let r2 = r1.subtract([&c]).unwrap();
drop(r1);
drop(r2);
drop(a);
drop(b);
drop(c);
}
#[test]
fn test_t02_multiple_reads_no_crash() {
let original = test_box();
let brep_data = shape_to_brep_bytes(&[original]);
for _ in 0..5 {
let _shape = cadrum::Solid::read_brep_binary(&mut brep_data.as_slice()).unwrap();
}
}
#[test]
fn test_t03_mesh_normals_count() {
let shape = test_box();
let mesh = cadrum::Solid::mesh(&[shape], 0.1).unwrap();
assert_eq!(mesh.normals.len(), mesh.vertices.len());
}
#[test]
fn test_t04_approximation_tolerance() {
let cyl = [Solid::cylinder(10.0, dvec3(0.0, 0.0, 1.0), 20.0)];
let mut has_difference = false;
for edge in cyl.iter().flat_map(|s| s.iter_edge()) {
let coarse = edge.approximation_segments(1.0).len();
let fine = edge.approximation_segments(0.01).len();
if fine > coarse {
has_difference = true;
}
}
assert!(has_difference, "Fine tolerance should produce more points than coarse");
}
#[test]
fn test_t05_translated_compound() {
let a = test_box();
let b = test_box_2();
let compound = a.union([&b]).unwrap();
let v = dvec3(100.0, 0.0, 0.0);
let orig_mesh = cadrum::Solid::mesh(&compound, 0.1).unwrap();
let shifted: Vec<Solid> = compound.into_iter().map(|s| s.translate(v)).collect();
let shifted_mesh = cadrum::Solid::mesh(&shifted, 0.1).unwrap();
assert_eq!(orig_mesh.vertices.len(), shifted_mesh.vertices.len());
for (o, s) in orig_mesh.vertices.iter().zip(shifted_mesh.vertices.iter()) {
assert!((s.x - o.x - v.x).abs() < 1e-6);
assert!((s.y - o.y - v.y).abs() < 1e-6);
assert!((s.z - o.z - v.z).abs() < 1e-6);
}
}
#[test]
fn test_t06_brep_roundtrip() {
let original = test_box();
let orig_mesh = cadrum::Solid::mesh([&original], 0.1).unwrap();
let brep_data = shape_to_brep_bytes([&original]);
let restored = cadrum::Solid::read_brep_binary(&mut brep_data.as_slice()).unwrap();
let rest_mesh = cadrum::Solid::mesh(&restored, 0.1).unwrap();
assert_eq!(orig_mesh.vertices.len(), rest_mesh.vertices.len());
for (o, r) in orig_mesh.vertices.iter().zip(rest_mesh.vertices.iter()) {
assert!((o.x - r.x).abs() < 1e-10);
assert!((o.y - r.y).abs() < 1e-10);
assert!((o.z - r.z).abs() < 1e-10);
}
}
#[test]
fn test_t08_boolean_returns_shape() {
let a = test_box();
let b = test_box_2();
let _union: Vec<Solid> = a.union([&b]).unwrap();
let _sub: Vec<Solid> = a.subtract([&b]).unwrap();
let _inter: Vec<Solid> = a.intersect([&b]).unwrap();
}
#[test]
fn test_hollow_cube_write_step() {
let outer = [Solid::cube(20.0, 20.0, 20.0).translate(dvec3(-10.0, -10.0, -10.0))];
let inner = [Solid::cube(10.0, 10.0, 10.0).translate(dvec3(-5.0, -5.0, -5.0))];
let hollow_cube = outer.subtract(&inner).unwrap();
std::fs::create_dir_all("out").unwrap();
let mut file = std::fs::File::create("out/hollow_cube.step").unwrap();
cadrum::Solid::write_step(&hollow_cube, &mut file).unwrap();
}
#[test]
fn test_half_space_intersect() {
let shape = test_box();
let half = [Solid::half_space(dvec3(5.0, 0.0, 0.0), dvec3(1.0, 0.0, 0.0))];
let result = shape.intersect(&half).unwrap();
assert!(!result.iter().all(|s| s.is_null()));
}
#[test]
fn test_cylinder() {
let cyl = [Solid::cylinder(5.0, dvec3(0.0, 0.0, 1.0), 10.0)];
let expected = std::f64::consts::PI * 5.0f64.powi(2) * 10.0;
assert!((cyl.iter().map(|s| s.volume()).sum::<f64>() - expected).abs() < 1e-6);
}
#[test]
fn test_brep_text_roundtrip() {
let original = test_box();
let mut text_data = Vec::new();
cadrum::Solid::write_brep_text([&original], &mut text_data).unwrap();
assert!(!text_data.is_empty());
let restored = cadrum::Solid::read_brep_text(&mut text_data.as_slice()).unwrap();
let orig_mesh = cadrum::Solid::mesh([&original], 0.1).unwrap();
let rest_mesh = cadrum::Solid::mesh(&restored, 0.1).unwrap();
assert_eq!(orig_mesh.vertices.len(), rest_mesh.vertices.len());
}