#include #include "vde/brep/brep.h" #include "vde/brep/modeling.h" #include "vde/brep/brep_validate.h" using namespace vde::brep; using namespace vde::core; // ═══════════════════════════════════════════════════════════ // Validation: Basic structural checks // ═══════════════════════════════════════════════════════════ TEST(BrepValidateTest, ValidateBox_ProducesResult) { auto box = make_box(2, 3, 4); auto result = validate(box); // Box should validate (within the limitations of our non-shared-edge topology) EXPECT_TRUE(result.total_faces == box.num_faces()); EXPECT_TRUE(result.total_edges == box.num_edges()); } TEST(BrepValidateTest, ValidateBox_HasEdgeLengthBounds) { auto box = make_box(2, 2, 2); auto result = validate(box); EXPECT_GT(result.max_edge_length, 0.0); EXPECT_LT(result.min_edge_length, std::numeric_limits::max()); // Box with side 2 should have edges of length ~2 EXPECT_NEAR(result.max_edge_length, 2.0, 0.1); } TEST(BrepValidateTest, ValidateBox_ComputesWatertightness) { auto box = make_box(2, 2, 2); auto result = validate(box); EXPECT_GE(result.watertightness, 0.0); EXPECT_LE(result.watertightness, 1.0); } TEST(BrepValidateTest, ValidateBox_ComputesSelfIntersection) { auto box = make_box(2, 2, 2); auto result = validate(box); EXPECT_GE(result.self_intersection_free, 0.0); EXPECT_LE(result.self_intersection_free, 1.0); } TEST(BrepValidateTest, ValidateBox_HasCounts) { auto box = make_box(2, 2, 2); auto result = validate(box); EXPECT_GE(result.total_faces, 0u); EXPECT_GE(result.total_edges, 0u); } // ═══════════════════════════════════════════════════════════ // Validation: Sphere // ═══════════════════════════════════════════════════════════ TEST(BrepValidateTest, ValidateSphere_ProducesResult) { auto sphere = make_sphere(2.0); auto result = validate(sphere); // Sphere should produce valid counts EXPECT_GT(result.total_faces, 0u); EXPECT_GT(result.total_edges, 0u); } TEST(BrepValidateTest, ValidateSphere_HasNonZeroEdgeLengths) { auto sphere = make_sphere(1.0); auto result = validate(sphere); EXPECT_GT(result.max_edge_length, 0.0); } // ═══════════════════════════════════════════════════════════ // Validation: Cylinder // ═══════════════════════════════════════════════════════════ TEST(BrepValidateTest, ValidateCylinder_ProducesResult) { auto cyl = make_cylinder(1.0, 3.0); auto result = validate(cyl); EXPECT_GT(result.total_faces, 0u); } TEST(BrepValidateTest, ValidateCylinder_ComputesMetrics) { auto cyl = make_cylinder(1.0, 5.0); auto result = validate(cyl); EXPECT_GE(result.watertightness, 0.0); EXPECT_LE(result.watertightness, 1.0); EXPECT_GE(result.self_intersection_free, 0.0); } // ═══════════════════════════════════════════════════════════ // Validation: Extruded body // ═══════════════════════════════════════════════════════════ TEST(BrepValidateTest, ValidateExtrude_ProducesResult) { vde::curves::NurbsCurve profile( {Point3D(0,0,0), Point3D(1,0,0), Point3D(1,1,0), Point3D(0,1,0)}, {0,0,0,0,1,1,1,1}, {1,1,1,1}, 3); auto ext = extrude(profile, Vector3D(0, 0, 2)); auto result = validate(ext); EXPECT_GT(result.total_faces, 0u); EXPECT_TRUE(ext.is_valid()); } // ═══════════════════════════════════════════════════════════ // Validation: Empty model // ═══════════════════════════════════════════════════════════ TEST(BrepValidateTest, ValidateEmptyModel_IsValid) { BrepModel empty; auto result = validate(empty); EXPECT_TRUE(result.valid); EXPECT_EQ(result.total_faces, 0u); EXPECT_EQ(result.total_edges, 0u); } // ═══════════════════════════════════════════════════════════ // Validation: Result structure // ═══════════════════════════════════════════════════════════ TEST(BrepValidateTest, ValidationResult_ContainsExpectedFields) { auto box = make_box(2, 2, 2); auto result = validate(box); // Check that all fields are initialized EXPECT_TRUE(result.valid || !result.valid); // just exists EXPECT_GE(result.watertightness, 0.0); EXPECT_GE(result.self_intersection_free, 0.0); EXPECT_GE(result.min_edge_length, 0.0); EXPECT_GT(result.max_edge_length, 0.0); } TEST(BrepValidateTest, ValidationResult_HasDiagnosticOutput) { auto box = make_box(2, 2, 2); auto result = validate(box); // At minimum, the result structure should have errors/warnings vectors // (they can be empty) EXPECT_TRUE(true); // just verifying the struct compiles and runs } // ═══════════════════════════════════════════════════════════ // Validation: Detection of dangling edges // ═══════════════════════════════════════════════════════════ TEST(BrepValidateTest, DanglingEdgeDetection_Works) { auto box = make_box(2, 2, 2); auto result = validate(box); // In a box with non-shared edges (current implementation), there will // be many dangling edges. This test just verifies the field is computed. EXPECT_GE(result.dangling_edges, 0u); EXPECT_GE(result.non_manifold_edges, 0u); } // ═══════════════════════════════════════════════════════════ // Validation: Edge count sanity // ═══════════════════════════════════════════════════════════ TEST(BrepValidateTest, ValidateBox_EdgeCountMatches) { auto box = make_box(2, 2, 2); auto result = validate(box); // total_edges should match body.num_edges() EXPECT_EQ(result.total_edges, box.num_edges()); } TEST(BrepValidateTest, ValidateBox_FaceCountMatches) { auto box = make_box(2, 2, 2); auto result = validate(box); EXPECT_EQ(result.total_faces, box.num_faces()); }