-// bool isEdgeCompatiballyMeshed(const TopoDS_Edge& edge, SMESH_subMesh* faceSubMesh)
-// {
-// if ( SMESH_subMesh* edgeSM = faceSubMesh->GetFather()->GetSubMeshContaining( edge ))
-// {
-// if ( SMESH_subMeshEventListenerData* otherFaceData =
-// edgeSM->GetEventListenerData( TEdgeMarker::getListener() ))
-// {
-// // compare hypothesis aplied to two disk faces sharing radial edges
-// SMESH_Mesh& mesh = *faceSubMesh->GetFather();
-// SMESH_Algo* radialQuadAlgo = mesh.GetGen()->GetAlgo(mesh, faceSubMesh->GetSubShape() );
-// SMESH_subMesh* otherFaceSubMesh = otherFaceData->mySubMeshes.front();
-// list <const SMESHDS_Hypothesis *> hyps1 =
-// radialQuadAlgo->GetUsedHypothesis( mesh, faceSubMesh->GetSubShape());
-// list <const SMESHDS_Hypothesis *> hyps2 =
-// radialQuadAlgo->GetUsedHypothesis( mesh, otherFaceSubMesh->GetSubShape());
-// if( hyps1.empty() && hyps2.empty() )
-// return true; // defaul hyps
-// if ( hyps1.size() != hyps2.size() )
-// return false;
-// return *hyps1.front() == *hyps2.front();
-// }
-// }
-// return false;
-// }
+ //================================================================================
+
+ int analyseFace(const TopoDS_Shape& aShape,
+ SMESH_Mesh* aMesh,
+ StdMeshers_FaceSidePtr& aCircSide,
+ StdMeshers_FaceSidePtr& aLinSide1,
+ StdMeshers_FaceSidePtr& aLinSide2)
+ {
+ const TopoDS_Face& face = TopoDS::Face( aShape );
+ aCircSide.reset(); aLinSide1.reset(); aLinSide2.reset();
+
+ list< TopoDS_Edge > edges;
+ list< int > nbEdgesInWire;
+ int nbWire = SMESH_Block::GetOrderedEdges ( face, edges, nbEdgesInWire );
+ if ( nbWire > 2 || nbEdgesInWire.front() < 1 ) return 0;
+
+ // remove degenerated EDGEs
+ list<TopoDS_Edge>::iterator edge = edges.begin();
+ while ( edge != edges.end() )
+ if ( SMESH_Algo::isDegenerated( *edge ))
+ edge = edges.erase( edge );
+ else
+ ++edge;
+ int nbEdges = edges.size();
+
+ // find VERTEXes between continues EDGEs
+ TopTools_MapOfShape contVV;
+ if ( nbEdges > 1 )
+ {
+ TopoDS_Edge ePrev = edges.back();
+ for ( edge = edges.begin(); edge != edges.end(); ++edge )
+ {
+ if ( SMESH_Algo::IsContinuous( ePrev, *edge ))
+ contVV.Add( SMESH_MesherHelper::IthVertex( 0, *edge ));
+ ePrev = *edge;
+ }
+ }
+ // 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 );
+ 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 ));
+ }
+
+ 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 );
+ }
+ }
+
+ return sides.size();
+ }