use lib3mf_core::model::{Geometry, Mesh, Model, Object, ObjectType, ResourceId};
use lib3mf_core::validation::{
ValidationLevel, ValidationReport, ValidationSeverity, validate_geometry,
};
fn create_cube() -> Mesh {
let mut mesh = Mesh::new();
mesh.add_vertex(0.0, 0.0, 0.0); mesh.add_vertex(1.0, 0.0, 0.0); mesh.add_vertex(1.0, 1.0, 0.0); mesh.add_vertex(0.0, 1.0, 0.0); mesh.add_vertex(0.0, 0.0, 1.0); mesh.add_vertex(1.0, 0.0, 1.0); mesh.add_vertex(1.0, 1.0, 1.0); mesh.add_vertex(0.0, 1.0, 1.0);
mesh.add_triangle(0, 2, 1);
mesh.add_triangle(0, 3, 2);
mesh.add_triangle(4, 5, 6);
mesh.add_triangle(4, 6, 7);
mesh.add_triangle(0, 1, 5);
mesh.add_triangle(0, 5, 4);
mesh.add_triangle(1, 2, 6);
mesh.add_triangle(1, 6, 5);
mesh.add_triangle(2, 3, 7);
mesh.add_triangle(2, 7, 6);
mesh.add_triangle(3, 0, 4);
mesh.add_triangle(3, 4, 7);
mesh
}
fn make_object(mesh: Mesh) -> Object {
Object {
id: ResourceId(1),
object_type: ObjectType::Model,
geometry: Geometry::Mesh(mesh),
name: None,
part_number: None,
uuid: None,
pid: None,
thumbnail: None,
pindex: None,
}
}
#[test]
fn test_perfect_cube() {
let mut model = Model::default();
let mesh = create_cube();
let object = make_object(mesh);
model.resources.add_object(object).unwrap();
let mut report = ValidationReport::default();
validate_geometry(&model, ValidationLevel::Paranoid, &mut report);
assert!(!report.has_errors(), "Perfect cube should have no errors");
assert!(
!report
.items
.iter()
.any(|i| i.severity == ValidationSeverity::Warning),
"Perfect cube should have no warnings"
);
}
#[test]
fn test_missing_face() {
let mut model = Model::default();
let mut mesh = create_cube();
mesh.triangles.pop();
mesh.triangles.pop();
let object = make_object(mesh);
model.resources.add_object(object).unwrap();
let mut report = ValidationReport::default();
validate_geometry(&model, ValidationLevel::Paranoid, &mut report);
assert!(
report.items.iter().any(|i| i.code == 4002),
"Should detect boundary edges (4002). Got: {:?}",
report.items
);
}
#[test]
fn test_flipped_face() {
let mut model = Model::default();
let mut mesh = create_cube();
let t0 = mesh.triangles[0];
mesh.triangles[0] = lib3mf_core::model::Triangle {
v1: t0.v1,
v2: t0.v3,
v3: t0.v2,
..Default::default()
};
let object = make_object(mesh);
model.resources.add_object(object).unwrap();
let mut report = ValidationReport::default();
validate_geometry(&model, ValidationLevel::Paranoid, &mut report);
assert!(
report.items.iter().any(|i| i.code == 4004),
"Should detect orientation mismatch (4004). Got: {:?}",
report.items
);
}
#[test]
fn test_degenerate_face() {
let mut model = Model::default();
let mut mesh = create_cube();
mesh.add_vertex(2.0, 0.0, 0.0); mesh.add_triangle(0, 1, 8);
let object = make_object(mesh);
model.resources.add_object(object).unwrap();
let mut report = ValidationReport::default();
validate_geometry(&model, ValidationLevel::Paranoid, &mut report);
assert!(
report.items.iter().any(|i| i.code == 4005),
"Should detect zero area triangle (4005). Got: {:?}",
report.items
);
}
#[test]
fn test_non_manifold_vertex() {
let mut model = Model::default();
let mut mesh = Mesh::new();
mesh.add_vertex(0.0, 0.0, 0.0); mesh.add_vertex(1.0, 0.0, 0.0); mesh.add_vertex(0.0, 1.0, 0.0); mesh.add_triangle(0, 1, 2);
mesh.add_vertex(-1.0, 0.0, 0.0); mesh.add_vertex(0.0, -1.0, 0.0); mesh.add_triangle(0, 3, 4);
let object = make_object(mesh);
model.resources.add_object(object).unwrap();
let mut report = ValidationReport::default();
validate_geometry(&model, ValidationLevel::Paranoid, &mut report);
assert!(
report.items.iter().any(|i| i.code == 4006),
"Should detect non-manifold vertex (4006). Got: {:?}",
report.items
);
}
#[test]
fn test_islands() {
let mut model = Model::default();
let mut mesh = Mesh::new();
mesh.add_vertex(0.0, 0.0, 0.0);
mesh.add_vertex(1.0, 0.0, 0.0);
mesh.add_vertex(0.0, 1.0, 0.0);
mesh.add_triangle(0, 1, 2);
mesh.add_vertex(10.0, 0.0, 0.0);
mesh.add_vertex(11.0, 0.0, 0.0);
mesh.add_vertex(10.0, 1.0, 0.0);
mesh.add_triangle(3, 4, 5);
let object = make_object(mesh);
model.resources.add_object(object).unwrap();
let mut report = ValidationReport::default();
validate_geometry(&model, ValidationLevel::Paranoid, &mut report);
assert!(
report.items.iter().any(|i| i.code == 4007),
"Should detect islands (4007). Got: {:?}",
report.items
);
}
#[test]
fn test_self_intersection() {
let mut model = Model::default();
let mut mesh = Mesh::new();
mesh.add_vertex(0.0, 1.0, 0.0); mesh.add_vertex(0.0, -1.0, 0.0); mesh.add_vertex(1.0, 0.0, 0.0); mesh.add_triangle(0, 1, 2);
mesh.add_vertex(0.5, 0.0, -1.0); mesh.add_vertex(0.5, 0.0, 1.0); mesh.add_vertex(-0.5, 0.0, 0.0); mesh.add_triangle(3, 4, 5);
let object = make_object(mesh);
model.resources.add_object(object).unwrap();
let mut report = ValidationReport::default();
validate_geometry(&model, ValidationLevel::Paranoid, &mut report);
assert!(
report.items.iter().any(|i| i.code == 4008),
"Should detect self-intersection (4008). Got: {:?}",
report.items
);
}