@@ -335,65 +335,127 @@ BoundingBox MeshTetInterface::volume_to_surface_mesh(UnstructuredMesh & mesh)
335335}
336336
337337
338- unsigned int MeshTetInterface ::check_hull_integrity ()
338+ std :: set < MeshTetInterface :: SurfaceIntegrity > MeshTetInterface ::check_hull_integrity () const
339339{
340340 // Check for easy return: if the Mesh is empty (i.e. if
341341 // somebody called triangulate_conformingDelaunayMesh on
342342 // a Mesh with no elements, then hull integrity check must
343343 // fail...
344344 if (_mesh .n_elem () == 0 )
345- return 3 ;
345+ return {EMPTY_MESH };
346+
347+ std ::set < MeshTetInterface ::SurfaceIntegrity > returnval ;
346348
347349 for (auto & elem : this -> _mesh .element_ptr_range ())
348350 {
349351 // Check for proper element type
350352 if (elem -> type () != TRI3 )
351- {
352- //libmesh_error_msg("ERROR: Some of the elements in the original mesh were not TRI3!");
353- return 1 ;
354- }
353+ returnval .insert (NON_TRI3 );
355354
356- for (auto neigh : elem -> neighbor_ptr_range ())
355+ for (auto s : elem -> side_index_range ())
357356 {
357+ const Elem * const neigh = elem -> neighbor_ptr (s );
358+
358359 if (neigh == nullptr )
359360 {
360- // libmesh_error_msg("ERROR: Non-convex hull, cannot be tetrahedralized.");
361- return 2 ;
361+ returnval .insert (MISSING_NEIGHBOR );
362+ continue ;
363+ }
364+
365+ // Make sure our neighbor points back to us
366+ const unsigned int nn = neigh -> which_neighbor_am_i (elem );
367+
368+ if (nn >= 3 )
369+ {
370+ returnval .insert (MISSING_BACKLINK );
371+ continue ;
372+ }
373+
374+ // Our neighbor should have the same the edge nodes we do on
375+ // the neighboring edgei
376+ const Node * const n1 = elem -> node_ptr (s );
377+ const Node * const n2 = elem -> node_ptr ((s + 1 )%3 );
378+
379+ const unsigned int i1 = neigh -> local_node (n1 -> id ());
380+ const unsigned int i2 = neigh -> local_node (n2 -> id ());
381+ if (i1 >= 3 || i2 >= 3 )
382+ {
383+ returnval .insert (BAD_NEIGHBOR_NODES );
384+ continue ;
385+ }
386+
387+ // It should have those edge nodes in the opposite order
388+ // (because they have the same orientation we do)
389+ if ((i2 + 1 )%3 != i1 )
390+ {
391+ returnval .insert (NON_ORIENTED );
392+ continue ;
393+ }
394+
395+ // And it should have those edge nodes in the expected
396+ // places relative to its neighbor link
397+ if (i2 != nn )
398+ {
399+ returnval .insert (BAD_NEIGHBOR_LINKS );
400+ continue ;
362401 }
363402 }
364403 }
365404
366- // If we made it here, return success!
367- return 0 ;
405+ // Return anything and everything we found
406+ return returnval ;
368407}
369408
370409
371410
372- void MeshTetInterface ::process_hull_integrity_result (unsigned result )
373- {
374- std ::ostringstream err_msg ;
375411
376- if (result != 0 )
377- {
378- err_msg << "Error! Conforming Delaunay mesh tetrahedralization requires a convex hull." << std ::endl ;
379412
380- if (result == 1 )
381- {
382- err_msg << "Non-TRI3 elements were found in the input Mesh. " ;
383- err_msg << "A constrained Delaunay tetrahedralization requires a convex hull of TRI3 elements." << std ::endl ;
384- }
413+ void MeshTetInterface ::process_hull_integrity_result
414+ (const std ::set < MeshTetInterface ::SurfaceIntegrity > & result ) const
415+ {
416+ std ::ostringstream err_msg ;
385417
386- if (result == 2 )
387- {
388- err_msg << "At least one triangle without three neighbors was found in the input Mesh. " ;
389- err_msg << "A constrained Delaunay tetrahedralization must be a triangular manifold without boundary." << std ::endl ;
390- }
418+ if (result .empty ()) // success
419+ return ;
391420
392- if (result == 3 )
393- err_msg << "The input Mesh was empty!" << std ::endl ;
421+ err_msg << "Error! Conforming Delaunay mesh tetrahedralization requires a convex hull." << std ::endl ;
394422
395- libmesh_error_msg (err_msg .str ());
423+ if (result .count (NON_TRI3 ))
424+ {
425+ err_msg << "At least one non-Tri3 element was found in the input boundary mesh. " ;
426+ err_msg << "Our constrained Delaunay tetrahedralization boundary must be a triangulation of Tri3 elements." << std ::endl ;
427+ }
428+ if (result .count (MISSING_NEIGHBOR ))
429+ {
430+ err_msg << "At least one triangle without three neighbors was found in the input boundary mesh. " ;
431+ err_msg << "A constrained Delaunay tetrahedralization boundary must be a triangular manifold without boundary." << std ::endl ;
432+ }
433+ if (result .count (EMPTY_MESH ))
434+ {
435+ err_msg << "The input boundary mesh was empty!" << std ::endl ;
436+ err_msg << "Our constrained Delaunay tetrahedralization boundary must be a triangulation of Tri3 elements." << std ::endl ;
437+ }
438+ if (result .count (MISSING_BACKLINK ))
439+ {
440+ err_msg << "At least one triangle neighbor without a return neighbor link was found in the input boundary mesh. " ;
441+ err_msg << "A constrained Delaunay tetrahedralization boundary must be a conforming and non-adaptively-refined mesh." << std ::endl ;
442+ }
443+ if (result .count (BAD_NEIGHBOR_NODES ))
444+ {
445+ err_msg << "At least one triangle neighbor without expected node links was found in the input boundary mesh. " ;
446+ err_msg << "A constrained Delaunay tetrahedralization boundary must be a conforming and non-adaptively-refined mesh." << std ::endl ;
396447 }
448+ if (result .count (NON_ORIENTED ))
449+ {
450+ err_msg << "At least one triangle neighbor with an inconsistent orientation was found in the input boundary mesh. " ;
451+ err_msg << "A constrained Delaunay tetrahedralization boundary must be an oriented Tri3 mesh." << std ::endl ;
452+ }
453+ if (result .count (BAD_NEIGHBOR_LINKS ))
454+ {
455+ err_msg << "At least one triangle neighbor with inconsistent node and neighbor links was found in the input boundary mesh." << std ::endl ;
456+ }
457+
458+ libmesh_error_msg (err_msg .str ());
397459}
398460
399461
0 commit comments