+ //================================================================================
+ /*!
+ * \brief Fix bad faces by smoothing
+ */
+ //================================================================================
+
+ void fixDistortedFaces( SMESH_MesherHelper& helper,
+ TSideVector& )
+ {
+ // Detect bad faces
+
+ bool haveBadFaces = false;
+
+ const TopoDS_Face& F = TopoDS::Face( helper.GetSubShape() );
+ SMESHDS_SubMesh* smDS = helper.GetMeshDS()->MeshElements( F );
+ if ( !smDS || smDS->NbElements() == 0 ) return;
+
+ SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
+ double prevArea2D = 0;
+ vector< const SMDS_MeshNode* > nodes;
+ vector< gp_XY > uv;
+ while ( faceIt->more() && !haveBadFaces )
+ {
+ const SMDS_MeshElement* face = faceIt->next();
+
+ // get nodes
+ nodes.resize( face->NbCornerNodes() );
+ SMDS_MeshElement::iterator n = face->begin_nodes();
+ for ( size_t i = 0; i < nodes.size(); ++n, ++i )
+ nodes[ i ] = *n;
+
+ // get UVs
+ const SMDS_MeshNode* inFaceNode = 0;
+ if ( helper.HasSeam() )
+ for ( size_t i = 0; ( i < nodes.size() && !inFaceNode ); ++i )
+ if ( !helper.IsSeamShape( nodes[ i ]->getshapeId() ))
+ inFaceNode = nodes[ i ];
+
+ uv.resize( nodes.size() );
+ for ( size_t i = 0; i < nodes.size(); ++i )
+ uv[ i ] = helper.GetNodeUV( F, nodes[ i ], inFaceNode );
+
+ // compare orientation of triangles
+ for ( int iT = 0, nbT = nodes.size()-2; iT < nbT; ++iT )
+ {
+ gp_XY v1 = uv[ iT+1 ] - uv[ 0 ];
+ gp_XY v2 = uv[ iT+2 ] - uv[ 0 ];
+ double area2D = v2 ^ v1;
+ if (( haveBadFaces = ( area2D * prevArea2D < 0 )))
+ break;
+ prevArea2D = area2D;
+ }
+ }
+
+ // Fix faces
+
+ if ( haveBadFaces )
+ {
+ SMESH_MeshEditor editor( helper.GetMesh() );
+
+ TIDSortedElemSet faces;
+ for ( faceIt = smDS->GetElements(); faceIt->more(); )
+ faces.insert( faces.end(), faceIt->next() );
+
+ // choose smoothing algo
+ //SMESH_MeshEditor:: SmoothMethod algo = SMESH_MeshEditor::CENTROIDAL;
+ bool isConcaveBoundary = false;
+ TError err;
+ TSideVector tgtWires =
+ StdMeshers_FaceSide::GetFaceWires( F, *helper.GetMesh(),/*skipMediumNodes=*/0, err);
+ for ( size_t iW = 0; iW < tgtWires.size() && !isConcaveBoundary; ++iW )
+ {
+ TopoDS_Edge prevEdge = tgtWires[iW]->Edge( tgtWires[iW]->NbEdges() - 1 );
+ for ( int iE = 0; iE < tgtWires[iW]->NbEdges() && !isConcaveBoundary; ++iE )
+ {
+ double angle = helper.GetAngle( prevEdge, tgtWires[iW]->Edge( iE ),
+ F, tgtWires[iW]->FirstVertex( iE ));
+ isConcaveBoundary = ( angle < -5. * M_PI / 180. );
+
+ prevEdge = tgtWires[iW]->Edge( iE );
+ }
+ }
+ SMESH_MeshEditor:: SmoothMethod algo =
+ isConcaveBoundary ? SMESH_MeshEditor::CENTROIDAL : SMESH_MeshEditor::LAPLACIAN;
+
+ // smoothing
+ set<const SMDS_MeshNode*> fixedNodes;
+ editor.Smooth( faces, fixedNodes, algo, /*nbIterations=*/ 10,
+ /*theTgtAspectRatio=*/1.0, /*the2D=*/false);
+ }
+ }
+