@@ -402,6 +402,87 @@ static void test_closed_detection(void) {
402402 printf ("done\n" );
403403}
404404
405+ /************************************************************************/
406+ /* Test: boundary edge (1 face on an edge) */
407+ /************************************************************************/
408+ static void test_boundary_edge (void ) {
409+ printf ("test_boundary_edge... " );
410+ /* Take a valid tetrahedron but remove the last face, replace with
411+ a face that shares no edge with it — leaving boundary edges
412+ where the removed face was. */
413+ vector3 verts [5 ] = {
414+ {0 , 0 , 0 }, {1 , 0 , 0 }, {0 , 1 , 0 }, {0 , 0 , 1 }, {2 , 2 , 2 }
415+ };
416+ int tris [4 * 3 ] = {
417+ 0 , 1 , 2 , /* face 0 */
418+ 0 , 1 , 3 , /* face 1 */
419+ 0 , 2 , 3 , /* face 2 */
420+ /* missing: 1, 2, 3 — replaced with unconnected face */
421+ 0 , 1 , 4 /* face 3: edge (1,2) and (2,3) now have only 1 face */
422+ };
423+ geometric_object obj = make_mesh (NULL , verts , 5 , tris , 4 );
424+ mesh * m = obj .subclass .mesh_data ;
425+ ASSERT_TRUE ("boundary edge mesh detected as not closed" , !m -> is_closed );
426+ geometric_object_destroy (obj );
427+ printf ("done\n" );
428+ }
429+
430+ /************************************************************************/
431+ /* Test: non-manifold edge (3+ faces sharing an edge) */
432+ /************************************************************************/
433+ static void test_nonmanifold_edge (void ) {
434+ printf ("test_nonmanifold_edge... " );
435+ /* A tetrahedron (4 faces) plus 2 extra faces sharing edge (0,1),
436+ giving that edge 4 adjacent faces instead of 2. */
437+ vector3 verts [6 ] = {
438+ {0 , 0 , 0 }, {1 , 0 , 0 }, {0 , 1 , 0 }, {0 , 0 , 1 },
439+ {0.5 , -1 , 0.5 }, {0.5 , -1 , -0.5 }
440+ };
441+ int tris [6 * 3 ] = {
442+ 0 , 1 , 2 , /* tetra face 0 — uses edge (0,1) */
443+ 0 , 1 , 3 , /* tetra face 1 — uses edge (0,1) */
444+ 0 , 2 , 3 , /* tetra face 2 */
445+ 1 , 2 , 3 , /* tetra face 3 */
446+ 0 , 1 , 4 , /* extra face — edge (0,1) now has 3 faces */
447+ 0 , 1 , 5 , /* extra face — edge (0,1) now has 4 faces */
448+ };
449+ geometric_object obj = make_mesh (NULL , verts , 6 , tris , 6 );
450+ mesh * m = obj .subclass .mesh_data ;
451+ ASSERT_TRUE ("non-manifold edge mesh detected as not closed" , !m -> is_closed );
452+ geometric_object_destroy (obj );
453+ printf ("done\n" );
454+ }
455+
456+ /************************************************************************/
457+ /* Test: isolated vertex (vertex not referenced by any face) */
458+ /************************************************************************/
459+ static void test_isolated_vertex (void ) {
460+ printf ("test_isolated_vertex... " );
461+ /* A valid tetrahedron plus an extra vertex that no face references.
462+ The mesh should still be detected as closed (isolated vertices
463+ don't affect edge manifold-ness). */
464+ vector3 verts [5 ] = {
465+ {1 , 1 , 1 }, {1 , -1 , -1 }, {-1 , 1 , -1 }, {-1 , -1 , 1 },
466+ {99 , 99 , 99 } /* isolated vertex */
467+ };
468+ int tris [4 * 3 ] = {
469+ 0 , 1 , 2 ,
470+ 0 , 3 , 1 ,
471+ 0 , 2 , 3 ,
472+ 1 , 3 , 2
473+ };
474+ geometric_object obj = make_mesh (NULL , verts , 5 , tris , 4 );
475+ mesh * m = obj .subclass .mesh_data ;
476+ ASSERT_TRUE ("mesh with isolated vertex still closed" , m -> is_closed );
477+
478+ /* Point inside tetrahedron should still work. */
479+ vector3 p = {0 , 0 , 0 };
480+ ASSERT_TRUE ("isolated vertex: centroid inside" , point_in_fixed_pobjectp (p , & obj ));
481+
482+ geometric_object_destroy (obj );
483+ printf ("done\n" );
484+ }
485+
405486/************************************************************************/
406487int main (void ) {
407488 geom_initialize ();
@@ -419,6 +500,9 @@ int main(void) {
419500 test_mesh_with_center ();
420501 test_open_mesh ();
421502 test_closed_detection ();
503+ test_boundary_edge ();
504+ test_nonmanifold_edge ();
505+ test_isolated_vertex ();
422506
423507 printf ("\n%d test failures\n" , test_failures );
424508 return test_failures > 0 ? 1 : 0 ;
0 commit comments