@@ -538,7 +538,8 @@ MeshTopology fromTriangles( const Triangulation & t, const BuildSettings & setti
538538}
539539
540540// two incident vertices can be found using this struct
541- struct IncidentVert {
541+ struct IncidentVert
542+ {
542543 FaceId f; // to find triangle in triangleToVertices vector
543544 VertId srcVert; // central vertex, used for sorting triangles per their incident vertices
544545 // the vertices of the triangle can be upgraded, so no reason to store VertId!
@@ -547,15 +548,20 @@ struct IncidentVert {
547548 : f(f)
548549 , srcVert( srcVert )
549550 {}
551+
552+ auto asPair () const { return std::make_pair ( srcVert, f ); }
553+ friend bool operator <( const IncidentVert& l, const IncidentVert& r ) { return l.asPair () < r.asPair (); }
550554};
551555
552- // to find the smallest connected sequences around central vertex, where a sequence does not repeat any neighbor vertex twice.
553- struct PathOverIncidentVert {
556+ // to find connected sequences around central vertex, where a sequence does not repeat any neighbor vertex twice.
557+ class PathOverIncidentVert
558+ {
554559 Triangulation& faceToVertices;
555560 // all iterators in [vertexBegIt, vertexEndIt) must have the same central vertex
556561 std::vector<IncidentVert>::iterator vertexBegIt, vertexEndIt;
557562 size_t lastUnvisitedIndex = 0 ; // pivot index. [vertexBegIt, vertexBegIt + lastUnvisitedIndex) - unvisited vertices
558563
564+ public:
559565 PathOverIncidentVert ( Triangulation& triangleToVertices,
560566 std::vector<IncidentVert>& incidentItemsVector, size_t beg, size_t end )
561567 : faceToVertices( triangleToVertices )
@@ -573,19 +579,25 @@ struct PathOverIncidentVert {
573579 // first unvisited vertex
574580 VertId getFirstVertex () const
575581 {
576- for ( auto v : faceToVertices[vertexBegIt->f ] )
577- if ( v != vertexBegIt->srcVert )
578- return v;
582+ // below selection ensures that getNextIncidentVertex( getFirstVertex(), true ) will find nextVertex in the very first triangle
583+ const auto & vs = faceToVertices[vertexBegIt->f ];
584+ if ( vs[0 ] == vertexBegIt->srcVert )
585+ return vs[1 ];
586+ if ( vs[1 ] == vertexBegIt->srcVert )
587+ return vs[2 ];
588+ if ( vs[2 ] == vertexBegIt->srcVert )
589+ return vs[0 ];
579590 assert ( false );
580591 return {};
581592 }
582593
583- // find incident unvisited vertex
584- VertId getNextIncidentVertex ( VertId v, bool triOrientation )
594+ // find incident unvisited vertex, in case of several option prefer finding the vertex not equal to preVertex
595+ VertId getNextIncidentVertex ( VertId v, bool triOrientation, VertId prevVertex = {} )
585596 {
586597 if ( lastUnvisitedIndex <= 0 )
587598 return VertId ( -1 );
588599
600+ auto prevIt = vertexBegIt + lastUnvisitedIndex;
589601 for ( auto it = vertexBegIt; it < vertexBegIt + lastUnvisitedIndex; ++it )
590602 {
591603 VertId nextVertex;
@@ -610,11 +622,22 @@ struct PathOverIncidentVert {
610622 }
611623 if ( nextVertex )
612624 {
613- --lastUnvisitedIndex;
614- std::iter_swap ( it, vertexBegIt + lastUnvisitedIndex );
615- return nextVertex;
625+ if ( nextVertex != prevVertex )
626+ {
627+ --lastUnvisitedIndex;
628+ std::iter_swap ( it, vertexBegIt + lastUnvisitedIndex );
629+ return nextVertex;
630+ }
631+ // prevVertex is a possible continuation, store it, and search for other options
632+ prevIt = it;
616633 }
617-
634+ }
635+ if ( prevIt < vertexBegIt + lastUnvisitedIndex )
636+ {
637+ // the only option is return in prevVertex
638+ --lastUnvisitedIndex;
639+ std::iter_swap ( prevIt, vertexBegIt + lastUnvisitedIndex );
640+ return prevVertex;
618641 }
619642 return {};
620643 }
@@ -684,11 +707,7 @@ void preprocessTriangles( const Triangulation & t, FaceBitSet * region, std::vec
684707 incidentVertVector.emplace_back ( f, vs[i] );
685708 }
686709
687- tbb::parallel_sort ( incidentVertVector.begin (), incidentVertVector.end (),
688- [] ( const IncidentVert& lhv, const IncidentVert& rhv ) -> bool
689- {
690- return lhv.srcVert < rhv.srcVert ;
691- } );
710+ tbb::parallel_sort ( incidentVertVector.begin (), incidentVertVector.end () );
692711}
693712
694713// path = {abcDefgD} => closedPath = {DefgD}; path = {abc}
@@ -747,6 +766,7 @@ size_t duplicateNonManifoldVertices( Triangulation & t, FaceBitSet * region, std
747766 bool triOrientation = true ;
748767 const VertId firstVertex = incidentItems.getFirstVertex ();
749768 visitedVertices.autoResizeSet ( firstVertex );
769+ VertId prevVertex = firstVertex;
750770 VertId nextVertex = incidentItems.getNextIncidentVertex ( firstVertex, triOrientation );
751771 if ( !nextVertex )
752772 {
@@ -759,7 +779,12 @@ size_t duplicateNonManifoldVertices( Triangulation & t, FaceBitSet * region, std
759779 path = { firstVertex, nextVertex };
760780 while ( true )
761781 {
762- nextVertex = incidentItems.getNextIncidentVertex ( nextVertex, triOrientation );
782+ {
783+ // prefer finding nextVertex not equal to prevVertex to maximize neighbour ring sizes
784+ auto currVertex = nextVertex;
785+ nextVertex = incidentItems.getNextIncidentVertex ( currVertex, triOrientation, prevVertex );
786+ prevVertex = currVertex;
787+ }
763788
764789 if ( !nextVertex )
765790 {
0 commit comments