@@ -504,11 +504,10 @@ int MMG5_setEdgeNmTag(MMG5_pMesh mesh, MMG5_Hash *hash) {
504504 /* Set edge tag and point tags to MG_REQ if the non-manifold edge shared
505505 * separated domains */
506506 if ( ph -> s > 3 ) {
507- start = ptt -> cc /4 ;
507+ start = ptt -> cc /4 ; // ptt->cc contains information about a supporting tetrahedron
508508 assert (start );
509509 pt = & mesh -> tetra [start ];
510510
511-
512511 for (ia = 0 ; ia < 6 ; ++ ia ) {
513512 ipa = MMG5_iare [ia ][0 ];
514513 ipb = MMG5_iare [ia ][1 ];
@@ -517,7 +516,6 @@ int MMG5_setEdgeNmTag(MMG5_pMesh mesh, MMG5_Hash *hash) {
517516 }
518517 assert (ia < 6 );
519518
520-
521519 /* Travel throug the shell of the edge until reaching a tetra without adjacent
522520 * or until reaching the starting tetra */
523521 iface = ptt -> cc %4 ;
@@ -802,6 +800,102 @@ int MMG5_setVertexNmTag(MMG5_pMesh mesh,uint16_t func(uint16_t) ) {
802800 return 1 ;
803801}
804802
803+ /**
804+ * \param mesh pointer towar the mesh structure.
805+ * \param hash hash table.
806+ * \return 1 if success, 0 if failed.
807+ *
808+ * Remove duplicate faces from the triangle mesh
809+ *
810+ */
811+ int MMG5_remdup (MMG5_pMesh mesh ,MMG5_Hash * hash ) {
812+ MMG5_pTria pt ;
813+ MMG5_hedge * ph ;
814+ MMG5_int dup ,k ,kk ,hmax ,ip0 ,ip1 ,ip2 ,min ,max ,sum ,key ;
815+
816+ dup = 0 ;
817+
818+ /* Allocate hash table params */
819+ hash -> siz = mesh -> np ;
820+ hmax = MG_MAX (hash -> siz ,mesh -> nt );
821+ hash -> max = hmax + 1 ;
822+ hash -> nxt = hash -> siz ;
823+ MMG5_ADD_MEM (mesh ,(hash -> max + 1 )* sizeof (MMG5_hedge ),"hash table" ,return 0 );
824+ MMG5_SAFE_CALLOC (hash -> item ,hash -> max + 1 ,MMG5_hedge ,return 0 );
825+
826+ /* Hash triangles */
827+ for (k = 1 ; k <=mesh -> nt ; k ++ ) {
828+ pt = & mesh -> tria [k ];
829+ if ( !MG_EOK (pt ) ) continue ;
830+
831+ ip0 = pt -> v [0 ];
832+ ip1 = pt -> v [1 ];
833+ ip2 = pt -> v [2 ];
834+
835+ min = MG_MIN (ip0 ,MG_MIN (ip1 ,ip2 ));
836+ max = MG_MAX (ip0 ,MG_MAX (ip1 ,ip2 ));
837+ sum = ip0 + ip1 + ip2 ;
838+
839+ key = (MMG5_KA * (int64_t )min + MMG5_KB * (int64_t )max + MMG5_KC * (int64_t )sum ) % hash -> siz ;
840+ ph = & hash -> item [key ];
841+
842+ /* Empty cell: store tria */
843+ if ( ph -> a == 0 ) {
844+ ph -> a = min ;
845+ ph -> b = max ;
846+ ph -> k = sum ;
847+ ph -> nxt = 0 ;
848+ continue ;
849+ }
850+
851+ while ( ph -> a ) {
852+ /* Remove duplicate */
853+ if ( ph -> a == min && ph -> b == max && ph -> k == sum ) {
854+ pt -> v [0 ] = 0 ;
855+ dup ++ ;
856+ break ;
857+ }
858+ else if ( !ph -> nxt ) {
859+ ph -> nxt = hash -> nxt ;
860+ hash -> nxt ++ ;
861+ ph = & hash -> item [ph -> nxt ];
862+ assert (ph );
863+
864+ if ( hash -> nxt >= hash -> max - 1 ) {
865+ if ( mesh -> info .ddebug ) {
866+ fprintf (stderr ,"\n ## Warning: %s: memory alloc problem (edge):"
867+ " %" MMG5_PRId "\n" ,__func__ ,hash -> max );
868+ }
869+ MMG5_TAB_RECALLOC (mesh ,hash -> item ,hash -> max ,MMG5_GAP ,MMG5_hedge ,
870+ "MMG5_edge" ,
871+ MMG5_DEL_MEM (mesh ,hash -> item );
872+ return 0 );
873+
874+ ph = & hash -> item [hash -> nxt ];
875+ }
876+
877+ ph -> a = min ;
878+ ph -> b = max ;
879+ ph -> k = sum ;
880+ ph -> nxt = 0 ;
881+ break ;
882+ }
883+ else {
884+ ph = & hash -> item [ph -> nxt ];
885+ }
886+ }
887+ }
888+
889+ /* Display information */
890+ if ( abs (mesh -> info .imprim ) > 5 && dup > 0 ) {
891+ fprintf (stdout ," ## " ); fflush (stdout );
892+ if ( dup > 0 ) fprintf (stdout ," %" MMG5_PRId " duplicate removed" ,dup );
893+ fprintf (stdout ,"\n" );
894+ }
895+
896+ return 1 ;
897+ }
898+
805899/**
806900 * \param mesh pointer towar the mesh structure.
807901 * \param hash edges hash table.
0 commit comments