Salome HOME
IPAL52499: Prismatic mesh is not computed on a prismatic shape
[modules/smesh.git] / src / StdMeshers / StdMeshers_FaceSide.cxx
index 66bae01e026929239ce2c94a07d007c5e86c18a5..1424e4226c40d4b92ffce8f8355cbbc73e6f79c1 100644 (file)
@@ -63,7 +63,7 @@ using namespace std;
  * \brief Constructor of a side of one edge
   * \param theFace - the face
   * \param theEdge - the edge
- */
 */
 //================================================================================
 
 StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
@@ -71,11 +71,15 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
                                          SMESH_Mesh*          theMesh,
                                          const bool           theIsForward,
                                          const bool           theIgnoreMediumNodes,
+                                         SMESH_MesherHelper*  theFaceHelper,
                                          SMESH_ProxyMesh::Ptr theProxyMesh)
 {
   std::list<TopoDS_Edge> edges(1,theEdge);
-  *this = StdMeshers_FaceSide( theFace, edges, theMesh, theIsForward,
-                               theIgnoreMediumNodes, theProxyMesh );
+  StdMeshers_FaceSide tmp( theFace, edges, theMesh, theIsForward,
+                           theIgnoreMediumNodes, theFaceHelper, theProxyMesh );
+  *this = tmp;
+
+  tmp.myHelper = NULL;
 }
 
 //================================================================================
@@ -84,12 +88,13 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
  */
 //================================================================================
 
-StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&      theFace,
-                                         std::list<TopoDS_Edge>& theEdges,
-                                         SMESH_Mesh*             theMesh,
-                                         const bool              theIsForward,
-                                         const bool              theIgnoreMediumNodes,
-                                         SMESH_ProxyMesh::Ptr    theProxyMesh)
+StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&            theFace,
+                                         const std::list<TopoDS_Edge>& theEdges,
+                                         SMESH_Mesh*                   theMesh,
+                                         const bool                    theIsForward,
+                                         const bool                    theIgnoreMediumNodes,
+                                         SMESH_MesherHelper*           theFaceHelper,
+                                         SMESH_ProxyMesh::Ptr          theProxyMesh)
 {
   int nbEdges = theEdges.size();
   myEdge.resize      ( nbEdges );
@@ -108,13 +113,19 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&      theFace,
   myMissingVertexNodes = false;
   myIgnoreMediumNodes  = theIgnoreMediumNodes;
   myDefaultPnt2d       = gp_Pnt2d( 1e+100, 1e+100 );
+  myHelper             = NULL;
   if ( !myProxyMesh ) myProxyMesh.reset( new SMESH_ProxyMesh( *theMesh ));
+  if ( theFaceHelper && theFaceHelper->GetSubShape() == myFace )
+  {
+    myHelper           = new SMESH_MesherHelper( * myProxyMesh->GetMesh() );
+    myHelper->CopySubShapeInfo( *theFaceHelper );
+  }
   if ( nbEdges == 0 ) return;
 
   SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
 
   int nbDegen = 0;
-  std::list<TopoDS_Edge>::iterator edge = theEdges.begin();
+  std::list<TopoDS_Edge>::const_iterator edge = theEdges.begin();
   for ( int index = 0; edge != theEdges.end(); ++index, ++edge )
   {
     int i = theIsForward ? index : nbEdges-index-1;
@@ -203,6 +214,7 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const StdMeshers_FaceSide*  theSide,
   myLast.push_back     ( theULast );
   myNormPar.push_back  ( 1. );
   myIsUniform.push_back( true );
+  myHelper       = NULL;
   myLength       = 0;
   myProxyMesh    = theSide->myProxyMesh;
   myDefaultPnt2d = *thePnt2d1;
@@ -260,6 +272,7 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec&     theSideNodes,
   }
 
   myFace       = theFace;
+  myHelper     = NULL;
   myPoints     = theSideNodes;
   myNbPonits   = myPoints.size();
   myNbSegments = myNbPonits + 1;
@@ -312,6 +325,17 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec&     theSideNodes,
   myEdgeLength.resize( 1, myLength );
 }
 
+//================================================================================
+/*!
+ * \brief Destructor
+ */
+//================================================================================
+
+StdMeshers_FaceSide::~StdMeshers_FaceSide()
+{
+  delete myHelper; myHelper = NULL;
+}
+
 //================================================================================
 /*
  * Return info on nodes on the side
@@ -326,12 +350,12 @@ const std::vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXCons
     if ( NbEdges() == 0 ) return myPoints;
 
     StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this );
-    SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
-    SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
-    fHelper.SetSubShape( myFace );
-    bool paramOK;
+    bool paramOK = true;
     double eps = 1e-100;
 
+    SMESH_MesherHelper  eHelper( *myProxyMesh->GetMesh() );
+    SMESH_MesherHelper& fHelper = *FaceHelper();
+
     // sort nodes of all edges by putting them into a map
 
     map< double, const SMDS_MeshNode*>            u2node;
@@ -448,8 +472,11 @@ const std::vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXCons
     if ((int) u2node.size() + nbProxyNodes != myNbPonits &&
         (int) u2node.size() + nbProxyNodes != NbPoints( /*update=*/true ))
     {
-      MESSAGE("Wrong node parameters on edges, u2node.size():"
-              <<u2node.size()<<" !=  myNbPonits:"<<myNbPonits);
+      return myPoints;
+    }
+    if (( u2node.size() > 0 ) &&
+        ( u2node.begin()->first < 0 || u2node.rbegin()->first > 1 ))
+    {
       return myPoints;
     }
 
@@ -466,25 +493,39 @@ const std::vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXCons
       if ( proxySubMesh[ iE ] ) // copy data from a proxy sub-mesh
       {
         const UVPtStructVec& edgeUVPtStruct = proxySubMesh[iE]->GetUVPtStructVec();
-        std::copy( edgeUVPtStruct.begin(), edgeUVPtStruct.end(), & points[iPt] );
+        UVPtStruct* pointsPtr = & points[iPt];
+        std::copy( edgeUVPtStruct.begin(), edgeUVPtStruct.end(), pointsPtr );
         // check orientation
         double du1 = edgeUVPtStruct.back().param - edgeUVPtStruct[0].param;
         double du2 = myLast[iE] - myFirst[iE];
         if ( du1 * du2 < 0 )
         {
-          std::reverse( & points[iPt], & points[iPt + edgeUVPtStruct.size()]);
+          std::reverse( pointsPtr, pointsPtr + edgeUVPtStruct.size());
           for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i )
-            points[iPt+i].normParam = 1. - points[iPt+i].normParam;
+            pointsPtr[i].normParam = 1. - pointsPtr[i].normParam;
         }
         // update normalized params
         if ( myEdge.size() > 1 ) {
-          for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i, ++iPt )
+          for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i )
           {
-            UVPtStruct & uvPt = points[iPt];
+            UVPtStruct & uvPt = pointsPtr[i];
             uvPt.normParam    = prevNormPar + uvPt.normParam * paramSize;
             uvPt.x = uvPt.y   = uvPt.normParam;
           }
-          --iPt; // to point to the 1st VERTEX of the next EDGE
+          iPt += edgeUVPtStruct.size() - 1; // to point to the 1st VERTEX of the next EDGE
+        }
+        // update UV on a seam EDGE
+        if ( fHelper.IsRealSeam( myEdgeID[ iE ]))
+        {
+          // check if points lye on the EDGE
+          const UVPtStruct& pm = edgeUVPtStruct[ edgeUVPtStruct.size()/2 ];
+          gp_Pnt         pNode = SMESH_TNodeXYZ( pm.node );
+          gp_Pnt         pCurv = myC3dAdaptor[ iE ].Value( pm.param );
+          double           tol = BRep_Tool::Tolerance( myEdge[ iE ]) * 10;
+          bool   isPointOnEdge = ( pNode.SquareDistance( pCurv ) < tol * tol );
+          if ( isPointOnEdge )
+            for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i )
+              pointsPtr[i].SetUV( myC2d[ iE ]->Value( pointsPtr[i].param ).XY() );
         }
       }
       else
@@ -492,7 +533,7 @@ const std::vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXCons
         for ( ; u_node != u2node.end(); ++u_node, ++iPt )
         {
           if ( myNormPar[ iE ]-eps < u_node->first )
-            break; // u_node is at VERTEX of the next EDGE 
+            break; // u_node is at VERTEX of the next EDGE
 
           UVPtStruct & uvPt = points[iPt];
           uvPt.node       = u_node->second;
@@ -601,9 +642,8 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
     if ( NbEdges() == 0 ) return resultNodes;
 
     //SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
-    SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
-    SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
-    fHelper.SetSubShape( myFace );
+    SMESH_MesherHelper  eHelper( *myProxyMesh->GetMesh() );
+    SMESH_MesherHelper& fHelper = * FaceHelper();
     bool paramOK = true;
 
     // Sort nodes of all edges putting them into a map
@@ -997,8 +1037,7 @@ int StdMeshers_FaceSide::NbPoints(const bool update) const
       }
     }
 
-    SMESH_MesherHelper helper( *myProxyMesh->GetMesh() );
-    helper.SetSubShape( myFace );
+    SMESH_MesherHelper* helper = FaceHelper();
 
     std::set< const SMDS_MeshNode* > vNodes;
     const int nbV = NbEdges() + !IsClosed();
@@ -1006,8 +1045,8 @@ int StdMeshers_FaceSide::NbPoints(const bool update) const
       if ( const SMDS_MeshNode* n = VertexNode( i ))
       {
         if ( !vNodes.insert( n ).second &&
-             ( helper.IsRealSeam  ( n->getshapeId() ) ||
-               helper.IsDegenShape( n->getshapeId() )))
+             ( helper->IsRealSeam  ( n->getshapeId() ) ||
+               helper->IsDegenShape( n->getshapeId() )))
           me->myNbPonits++;
       }
       else
@@ -1224,9 +1263,14 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face&   theFace,
                                               SMESH_Mesh &         theMesh,
                                               const bool           theIgnoreMediumNodes,
                                               TError &             theError,
+                                              SMESH_MesherHelper*  theFaceHelper,
                                               SMESH_ProxyMesh::Ptr theProxyMesh,
                                               const bool           theCheckVertexNodes)
 {
+  SMESH_MesherHelper helper( theMesh );
+  if ( theFaceHelper && theFaceHelper->GetSubShape() == theFace )
+    helper.CopySubShapeInfo( *theFaceHelper );
+
   list< TopoDS_Edge > edges, internalEdges;
   list< int > nbEdgesInWires;
   int nbWires = SMESH_Block::GetOrderedEdges (theFace, edges, nbEdgesInWires);
@@ -1270,7 +1314,7 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face&   theFace,
 
     StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, wireEdges, &theMesh,
                                                          /*isForward=*/true, theIgnoreMediumNodes,
-                                                         theProxyMesh );
+                                                         &helper, theProxyMesh );
     wires[ iW ] = StdMeshers_FaceSidePtr( wire );
     from = to;
   }
@@ -1278,7 +1322,7 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face&   theFace,
   {
     StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, internalEdges.back(), &theMesh,
                                                          /*isForward=*/true, theIgnoreMediumNodes,
-                                                         theProxyMesh );
+                                                         &helper, theProxyMesh );
     wires.push_back( StdMeshers_FaceSidePtr( wire ));
     internalEdges.pop_back();
   }
@@ -1334,3 +1378,20 @@ bool StdMeshers_FaceSide::IsClosed() const
 {
   return myEdge.empty() ? false : FirstVertex().IsSame( LastVertex() );
 }
+
+//================================================================================
+/*!
+ * \brief Return a helper initialized with the FACE
+ */
+//================================================================================
+
+SMESH_MesherHelper* StdMeshers_FaceSide::FaceHelper() const
+{
+  StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this );
+  if ( !myHelper && myProxyMesh )
+  {
+    me->myHelper = new SMESH_MesherHelper( *myProxyMesh->GetMesh() );
+    me->myHelper->SetSubShape( myFace );
+  }
+  return me->myHelper;
+}