Salome HOME
IPAL52781: Orientation of a wall face created by revolution is wrong
[modules/smesh.git] / src / StdMeshers / StdMeshers_FaceSide.cxx
index 869e6532b4b34cf0ab5823837239ae28eb73920c..2625b9fb1322eab64c256b743d3c76a64c076069 100644 (file)
@@ -113,7 +113,6 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
 
   int nbDegen = 0;
   list<TopoDS_Edge>::iterator edge = theEdges.begin();
-  TopoDS_Iterator vExp;
   for ( int index = 0; edge != theEdges.end(); ++index, ++edge )
   {
     int i = theIsForward ? index : nbEdges-index-1;
@@ -150,7 +149,7 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
       }
       else
       {
-        const TopoDS_Vertex& V = TopoDS::Vertex( vExp.Value() );
+        const TopoDS_Vertex& V = SMESH_MesherHelper::IthVertex( 0, *edge );
         Handle(Geom_Curve) C3d = new Geom_Line( BRep_Tool::Pnt( V ), gp::DX() );
         myC3dAdaptor[i].Load( C3d, 0, 0.5 * BRep_Tool::Tolerance( V ));
       }
@@ -312,7 +311,9 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
 
     StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this );
     SMESHDS_Mesh*    meshDS = myProxyMesh->GetMeshDS();
-    SMESH_MesherHelper helper( *myProxyMesh->GetMesh() );
+    SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
+    SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
+    fHelper.SetSubShape( myFace );
     bool paramOK;
     double eps = 1e-100;
 
@@ -347,19 +348,20 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
       const double  prevNormPar = ( iE == 0 ? 0 : myNormPar[ iE-1 ]); // normalized param
       if ( node ) // nodes on internal vertices may be missing
       {
-        if ( vertexNodes.insert( node ).second )
+        if ( vertexNodes.insert( node ).second ||
+             fHelper.IsRealSeam  ( node->getshapeId() ) ||
+             fHelper.IsDegenShape( node->getshapeId() ))
           u2node.insert( u2node.end(), make_pair( prevNormPar, node ));
       }
       else if ( iE == 0 )
       {
-        if ( nodes.empty() ) {
-          for ( ++iE; iE < myEdge.size(); ++iE )
-            if (( node = VertexNode( iE ))) {
-              u2node.insert( make_pair( prevNormPar, node ));
-              break;
-            }
-          --iE;
-        }
+        for ( ++iE; iE < myEdge.size(); ++iE )
+          if (( node = VertexNode( iE ))) {
+            u2node.insert( make_pair( prevNormPar, node ));
+            break;
+          }
+        --iE;
+
         if ( !node )
           return myPoints;
         vertexNodes.insert( node );
@@ -374,12 +376,12 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
         u2nodeVec.clear();
         double paramSize = myLast[iE] - myFirst[iE];
         double r         = myNormPar[iE] - prevNormPar;
-        helper.SetSubShape( myEdge[iE] );
-        helper.ToFixNodeParameters( true );
+        eHelper.SetSubShape( myEdge[iE] );
+        eHelper.ToFixNodeParameters( true );
         if ( !myIsUniform[iE] )
           for ( size_t i = 0; i < nodes.size(); ++i )
           {
-            double     u = helper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
+            double     u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
             double aLenU = GCPnts_AbscissaPoint::Length( me->myC3dAdaptor[iE], myFirst[iE], u );
             if ( myEdgeLength[iE] < aLenU ) // nonregression test "3D_mesh_NETGEN/G6"
             {
@@ -392,7 +394,7 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
         if ( u2nodeVec.empty() )
           for ( size_t i = 0; i < nodes.size(); ++i )
           {
-            double u = helper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
+            double u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
             // paramSize is signed so orientation is taken into account
             double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize;
             u2nodeVec.push_back( make_pair( normPar, nodes[i] ));
@@ -402,12 +404,13 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
       }
     } // loop on myEdge's
 
-    if ( u2node.empty() ) return myPoints;
-
     // Add 2nd VERTEX node for a last EDGE
+    if ( !proxySubMesh.back() )
     {
+      if ( u2node.empty() ) return myPoints;
+
       const SMDS_MeshNode* node;
-      if ( IsClosed() )
+      if ( IsClosed() && !proxySubMesh[0] )
         node = u2node.begin()->second;
       else
       {
@@ -417,8 +420,11 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
         if ( !node )
           return myPoints;
       }
-      if ( u2node.rbegin()->second == node )
+      if ( u2node.rbegin()->second == node &&
+           !fHelper.IsRealSeam  ( node->getshapeId() ) &&
+           !fHelper.IsDegenShape( node->getshapeId() ))
         u2node.erase( --u2node.end() );
+
       u2node.insert( u2node.end(), make_pair( 1., node ));
     }
 
@@ -577,14 +583,16 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
     if ( NbEdges() == 0 ) return resultNodes;
 
     SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
-    SMESH_MesherHelper helper(*myProxyMesh->GetMesh());
+    SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
+    SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
+    fHelper.SetSubShape( myFace );
     bool paramOK = true;
 
     // Sort nodes of all edges putting them into a map
 
-    map< double, const SMDS_MeshNode*>        u2node;
-    vector<const SMDS_MeshNode*>              nodes;
-    set<const SMDS_MeshNode*>                 vertexNodes;
+    map< double, const SMDS_MeshNode*> u2node;
+    vector<const SMDS_MeshNode*>       nodes;
+    set<const SMDS_MeshNode*>          vertexNodes;
     int iE = 0, iEnd = myEdge.size();
     if ( theEdgeInd >= 0 )
     {
@@ -607,7 +615,9 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
       // Add 1st vertex node of a current EDGE
       const SMDS_MeshNode* node = VertexNode( iE );
       if ( node ) { // nodes on internal vertices may be missing
-        if ( vertexNodes.insert( node ).second )
+        if ( vertexNodes.insert( node ).second ||
+             fHelper.IsRealSeam  ( node->getshapeId() ) ||
+             fHelper.IsDegenShape( node->getshapeId() ))
           u2node.insert( make_pair( prevNormPar, node ));
       }
       else if ( iE == 0 )
@@ -633,11 +643,11 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
       {
         double paramSize = myLast[iE] - myFirst[iE];
         double r         = myNormPar[iE] - prevNormPar;
-        helper.SetSubShape( myEdge[iE] );
-        helper.ToFixNodeParameters( true );
+        eHelper.SetSubShape( myEdge[iE] );
+        eHelper.ToFixNodeParameters( true );
         for ( size_t i = 0; i < nodes.size(); ++i )
         {
-          double u = helper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
+          double u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
           // paramSize is signed so orientation is taken into account
           double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize;
           u2node.insert( u2node.end(), make_pair( normPar, nodes[i] ));
@@ -661,20 +671,26 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
         if ( !node )
           return resultNodes;
       }
-      if ( u2node.rbegin()->second == node )
+      if ( u2node.rbegin()->second == node &&
+           !fHelper.IsRealSeam  ( node->getshapeId() ) &&
+           !fHelper.IsDegenShape( node->getshapeId() ))
         u2node.erase( --u2node.end() );
+
       u2node.insert( u2node.end(), make_pair( 1., node ));
     }
 
     // Fill the result vector
 
-    if ( u2node.size() == myNbPonits )
+    if ( theEdgeInd < 0 &&
+         u2node.size() != myNbPonits &&
+         u2node.size() != NbPoints( /*update=*/true ))
     {
-      resultNodes.reserve( u2node.size() );
-      map< double, const SMDS_MeshNode*>::iterator u2n = u2node.begin();
-      for ( ; u2n != u2node.end(); ++u2n )
-        resultNodes.push_back( u2n->second );
+      u2node.clear();
     }
+    resultNodes.reserve( u2node.size() );
+    map< double, const SMDS_MeshNode*>::iterator u2n = u2node.begin();
+    for ( ; u2n != u2node.end(); ++u2n )
+      resultNodes.push_back( u2n->second );
   }
   else
   {
@@ -708,9 +724,8 @@ bool StdMeshers_FaceSide::GetEdgeNodes(size_t                        i,
 
   if ( inlude1stVertex )
   {
-    const SMDS_MeshNode* n0 = VertexNode( i );
-    if ( !n0 ) return false;
-    nodes.push_back( n0 );
+    if ( const SMDS_MeshNode* n0 = VertexNode( i ))
+      nodes.push_back( n0 );
   }
 
   if ( sm && ( sm->NbElements() > 0 || sm->NbNodes() > 0 ))
@@ -765,9 +780,8 @@ bool StdMeshers_FaceSide::GetEdgeNodes(size_t                        i,
 
   if ( inludeLastVertex )
   {
-    const SMDS_MeshNode* n1 = VertexNode( i+1 );
-    if ( !n1 ) return false;
-    nodes.push_back( n1 );
+    if ( const SMDS_MeshNode* n1 = VertexNode( i+1 ))
+      nodes.push_back( n1 );
   }
   return true;
 }
@@ -944,27 +958,44 @@ int StdMeshers_FaceSide::NbPoints(const bool update) const
     me->myNbSegments = 0;
     me->myMissingVertexNodes = false;
 
+    vector<const SMDS_MeshNode*> nodes;
     for ( int i = 0; i < NbEdges(); ++i )
     {
-      if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( Edge(i) )) {
-        int nbN = sm->NbNodes();
-        if ( sm->NbElements() > 0 ) {
-          nbN = sm->NbElements() - 1; // nodes can be moved to other shapes by MergeNodes()
-          if ( !myIgnoreMediumNodes &&
-               sm->GetElements()->next()->IsQuadratic() )
-            nbN += sm->NbElements();
+      if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( Edge(i) ))
+      {
+        if ( sm->NbNodes() == sm->NbElements()-1 || sm->NbElements() == 0 )
+        {
+          me->myNbPonits += sm->NbNodes();
+          if ( myIgnoreMediumNodes && sm->IsQuadratic() )
+            me->myNbPonits -= sm->NbElements();
+        }
+        else // nodes can be moved to other shapes by MergeNodes()
+        {
+          nodes.clear();
+          GetEdgeNodes( i, nodes, /*v1=*/false, /*v2=*/false );
+          me->myNbPonits += nodes.size();
         }
-        me->myNbPonits   += nbN;
         me->myNbSegments += sm->NbElements();
       }
     }
 
+    SMESH_MesherHelper helper( *myProxyMesh->GetMesh() );
+    helper.SetSubShape( myFace );
+
     std::set< const SMDS_MeshNode* > vNodes;
-    for ( int i = 0; i <= NbEdges(); ++i )
+    const int nbV = NbEdges() + !IsClosed();
+    for ( int i = 0; i < nbV; ++i )
       if ( const SMDS_MeshNode* n = VertexNode( i ))
-        vNodes.insert( n );
+      {
+        if ( !vNodes.insert( n ).second &&
+             ( helper.IsRealSeam  ( n->getshapeId() ) ||
+               helper.IsDegenShape( n->getshapeId() )))
+          me->myNbPonits++;
+      }
       else
+      {
         me->myMissingVertexNodes = true;
+      }
     me->myNbPonits += vNodes.size();
 
     if ( IsClosed() )