+ // make edges start from a non-continues VERTEX
+ if ( 1 < contVV.Extent() && contVV.Extent() < nbEdges )
+ {
+ while ( contVV.Contains( SMESH_MesherHelper::IthVertex( 0, edges.front() )))
+ edges.splice( edges.end(), edges, edges.begin() );
+ }
+
+ // make face sides
+ TSideVector sides;
+ while ( !edges.empty() )
+ {
+ list< TopoDS_Edge > sideEdges;
+ sideEdges.splice( sideEdges.end(), edges, edges.begin() );
+ while ( !edges.empty() &&
+ contVV.Contains( SMESH_MesherHelper::IthVertex( 0, edges.front() )))
+ sideEdges.splice( sideEdges.end(), edges, edges.begin() );
+
+ StdMeshers_FaceSidePtr side;
+ if ( aMesh )
+ side = StdMeshers_FaceSide::New( face, sideEdges, aMesh,
+ /*isFwd=*/true, /*skipMedium=*/ true, helper );
+ sides.push_back( side );
+ }
+
+ if ( !aMesh ) // call from IsApplicable()
+ return sides.size();
+
+ if ( sides.size() > 3 )
+ return sides.size();
+
+ if ( nbWire == 2 && (( sides.size() != 2 ) ||
+ ( sides[0]->IsClosed() && sides[1]->IsClosed() ) ||
+ ( !sides[0]->IsClosed() && !sides[1]->IsClosed() )))
+ return -1;
+
+ // detect an elliptic side
+
+ if ( sides.size() == 1 )
+ {
+ aCircSide = sides[0];
+ return sides.size();
+ }
+
+ // sort sides by deviation from a straight line
+ multimap< double, int > deviation2sideInd;
+ const double nbSamples = 7;
+ for ( size_t iS = 0; iS < sides.size(); ++iS )
+ {
+ gp_Pnt pf = BRep_Tool::Pnt( sides[iS]->FirstVertex() );
+ gp_Pnt pl = BRep_Tool::Pnt( sides[iS]->LastVertex() );
+ gp_Vec v1( pf, pl );
+ double v1Len = v1.Magnitude();
+ if ( v1Len < std::numeric_limits< double >::min() )
+ {
+ deviation2sideInd.insert( make_pair( sides[iS]->Length(), iS )); // the side seems closed
+ continue;
+ }
+ double devia = 0;
+ for ( int i = 0; i < nbSamples; ++i )
+ {
+ gp_Pnt pi( sides[iS]->Value3d(( i + 1 ) / nbSamples ));
+ gp_Vec vi( pf, pi );
+ double h = 0.5 * v1.Crossed( vi ).Magnitude() / v1Len;
+ devia = Max( devia, h );
+ }
+ deviation2sideInd.insert( make_pair( devia, iS ));
+ }
+ double maxDevi = deviation2sideInd.rbegin()->first;
+ if ( maxDevi < 1e-7 && sides.size() == 3 )
+ {
+ // a triangle FACE; use a side with the most outstanding length as an elliptic one
+ deviation2sideInd.clear();
+ multimap< double, int > len2sideInd;
+ for ( size_t iS = 0; iS < sides.size(); ++iS )
+ len2sideInd.insert( make_pair( sides[iS]->Length(), iS ));
+
+ multimap< double, int >::iterator l2i = len2sideInd.begin();
+ double len0 = l2i->first;
+ double len1 = (++l2i)->first;
+ double len2 = (++l2i)->first;
+ if ( len1 - len0 > len2 - len1 )
+ deviation2sideInd.insert( make_pair( 0., len2sideInd.begin()->second ));
+ else
+ deviation2sideInd.insert( make_pair( 0., len2sideInd.rbegin()->second ));
+ }
+
+ int iCirc = deviation2sideInd.rbegin()->second;
+ aCircSide = sides[ iCirc ];
+ aLinSide1 = sides[( iCirc + 1 ) % sides.size() ];
+ if ( sides.size() > 2 )
+ {
+ aLinSide2 = sides[( iCirc + 2 ) % sides.size() ];
+ aLinSide2->Reverse(); // to be "parallel" to aLinSide1
+ }
+
+ if (( nbWire == 2 && aLinSide1 ) &&
+ ( aLinSide1->Edge(0).Orientation() == TopAbs_INTERNAL ) &&
+ ( aCircSide->IsClosed() ))
+ {
+ // assure that aCircSide starts at aLinSide1
+ TopoDS_Vertex v0 = aLinSide1->FirstVertex();
+ TopoDS_Vertex v1 = aLinSide1->LastVertex();
+ if ( ! aCircSide->FirstVertex().IsSame( v0 ) &&
+ ! aCircSide->FirstVertex().IsSame( v1 ))
+ {
+ int iE = 0;
+ for ( ; iE < aCircSide->NbEdges(); ++iE )
+ if ( aCircSide->FirstVertex(iE).IsSame( v0 ) ||
+ aCircSide->FirstVertex(iE).IsSame( v1 ))
+ break;
+ if ( iE == aCircSide->NbEdges() )
+ return -2;
+
+ edges.clear();
+ for ( int i = 0; i < aCircSide->NbEdges(); ++i, ++iE )
+ edges.push_back( aCircSide->Edge( iE % aCircSide->NbEdges() ));
+
+ aCircSide = StdMeshers_FaceSide::New( face, edges, aMesh,
+ /*isFwd=*/true, /*skipMedium=*/ true, helper );
+ }
+ }
+
+ return sides.size();