+//================================================================================
+/*!
+ * \brief Try to fix triangles with high aspect ratio by swaping diagonals
+ */
+//================================================================================
+
+void _ViscousBuilder::fixBadFaces(const TopoDS_Face& F, SMESH_MesherHelper& helper)
+{
+ SMESH::Controls::AspectRatio qualifier;
+ SMESH::Controls::TSequenceOfXYZ points(3), points1(3), points2(3);
+ const double maxAspectRatio = 4.;
+
+ // find bad triangles
+
+ vector< const SMDS_MeshElement* > badTrias;
+ vector< double > badAspects;
+ SMESHDS_SubMesh* sm = helper.GetMeshDS()->MeshElements( F );
+ SMDS_ElemIteratorPtr fIt = sm->GetElements();
+ while ( fIt->more() )
+ {
+ const SMDS_MeshElement * f = fIt->next();
+ if ( f->NbCornerNodes() != 3 ) continue;
+ for ( int iP = 0; iP < 3; ++iP ) points(iP+1) = SMESH_TNodeXYZ( f->GetNode(iP));
+ double aspect = qualifier.GetValue( points );
+ if ( aspect > maxAspectRatio )
+ {
+ badTrias.push_back( f );
+ badAspects.push_back( aspect );
+ }
+ }
+ if ( badTrias.empty() )
+ return;
+
+ // find couples of faces to swap diagonal
+
+ typedef pair < const SMDS_MeshElement* , const SMDS_MeshElement* > T2Trias;
+ vector< T2Trias > triaCouples;
+
+ TIDSortedElemSet involvedFaces, emptySet;
+ for ( size_t iTia = 0; iTia < badTrias.size(); ++iTia )
+ {
+ T2Trias trias [3];
+ double aspRatio [3];
+ int i1, i2, i3;
+
+ involvedFaces.insert( badTrias[iTia] );
+ for ( int iP = 0; iP < 3; ++iP )
+ points(iP+1) = SMESH_TNodeXYZ( badTrias[iTia]->GetNode(iP));
+
+ // find triangles adjacent to badTrias[iTia] with better aspect ratio after diag-swaping
+ int bestCouple = -1;
+ for ( int iSide = 0; iSide < 3; ++iSide )
+ {
+ const SMDS_MeshNode* n1 = badTrias[iTia]->GetNode( iSide );
+ const SMDS_MeshNode* n2 = badTrias[iTia]->GetNode(( iSide+1 ) % 3 );
+ trias [iSide].first = badTrias[iTia];
+ trias [iSide].second = SMESH_MeshEditor::FindFaceInSet( n1, n2, emptySet, involvedFaces,
+ & i1, & i2 );
+ if ( ! trias[iSide].second || trias[iSide].second->NbCornerNodes() != 3 )
+ continue;
+
+ // aspect ratio of an adjacent tria
+ for ( int iP = 0; iP < 3; ++iP )
+ points2(iP+1) = SMESH_TNodeXYZ( trias[iSide].second->GetNode(iP));
+ double aspectInit = qualifier.GetValue( points2 );
+
+ // arrange nodes as after diag-swaping
+ if ( helper.WrapIndex( i1+1, 3 ) == i2 )
+ i3 = helper.WrapIndex( i1-1, 3 );
+ else
+ i3 = helper.WrapIndex( i1+1, 3 );
+ points1 = points;
+ points1( 1+ iSide ) = points2( 1+ i3 );
+ points2( 1+ i2 ) = points1( 1+ ( iSide+2 ) % 3 );
+
+ // aspect ratio after diag-swaping
+ aspRatio[ iSide ] = qualifier.GetValue( points1 ) + qualifier.GetValue( points2 );
+ if ( aspRatio[ iSide ] > aspectInit + badAspects[ iTia ] )
+ continue;
+
+ if ( bestCouple < 0 || aspRatio[ bestCouple ] > aspRatio[ iSide ] )
+ bestCouple = iSide;
+ }
+
+ if ( bestCouple >= 0 )
+ {
+ triaCouples.push_back( trias[bestCouple] );
+ involvedFaces.insert ( trias[bestCouple].second );
+ }
+ else
+ {
+ involvedFaces.erase( badTrias[iTia] );
+ }
+ }
+ if ( triaCouples.empty() )
+ return;
+
+ // swap diagonals
+
+ SMESH_MeshEditor editor( helper.GetMesh() );
+ dumpFunction(SMESH_Comment("beforeSwapDiagonals_F")<<helper.GetSubShapeID());
+ for ( size_t i = 0; i < triaCouples.size(); ++i )
+ {
+ dumpChangeNodes( triaCouples[i].first );
+ dumpChangeNodes( triaCouples[i].second );
+ editor.InverseDiag( triaCouples[i].first, triaCouples[i].second );
+ }
+ dumpFunctionEnd();
+
+ // just for debug dump resulting triangles
+ dumpFunction(SMESH_Comment("swapDiagonals_F")<<helper.GetSubShapeID());
+ for ( size_t i = 0; i < triaCouples.size(); ++i )
+ {
+ dumpChangeNodes( triaCouples[i].first );
+ dumpChangeNodes( triaCouples[i].second );
+ }
+}
+