Salome HOME
IPAL53863: MG-CADSurf + Viscous Layers 2D on a cylindrical face ==> crash
[modules/smesh.git] / src / StdMeshers / StdMeshers_FaceSide.cxx
index 3849040e995afa5de3d232518f36b7dd3410fdac..0c7c334f20cd7e4b1fbf33411756b737a3a01612 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -56,6 +56,8 @@
 
 #include "utilities.h"
 
+using namespace std;
+
 //================================================================================
 /*!
  * \brief Constructor of a side of one edge
@@ -71,7 +73,7 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
                                          const bool           theIgnoreMediumNodes,
                                          SMESH_ProxyMesh::Ptr theProxyMesh)
 {
-  list<TopoDS_Edge> edges(1,theEdge);
+  std::list<TopoDS_Edge> edges(1,theEdge);
   *this = StdMeshers_FaceSide( theFace, edges, theMesh, theIsForward,
                                theIgnoreMediumNodes, theProxyMesh );
 }
@@ -82,12 +84,12 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
  */
 //================================================================================
 
-StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
-                                         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,
+                                         std::list<TopoDS_Edge>& theEdges,
+                                         SMESH_Mesh*             theMesh,
+                                         const bool              theIsForward,
+                                         const bool              theIgnoreMediumNodes,
+                                         SMESH_ProxyMesh::Ptr    theProxyMesh)
 {
   int nbEdges = theEdges.size();
   myEdge.resize      ( nbEdges );
@@ -112,7 +114,7 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
   SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
 
   int nbDegen = 0;
-  list<TopoDS_Edge>::iterator edge = theEdges.begin();
+  std::list<TopoDS_Edge>::iterator edge = theEdges.begin();
   for ( int index = 0; edge != theEdges.end(); ++index, ++edge )
   {
     int i = theIsForward ? index : nbEdges-index-1;
@@ -142,7 +144,6 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
         double p4 = myFirst[i]+(myLast[i]-myFirst[i])/4.;
         double d2 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p2 );
         double d4 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p4 );
-        //cout<<"len = "<<len<<"  d2 = "<<d2<<"  fabs(2*d2/len-1.0) = "<<fabs(2*d2/len-1.0)<<endl;
         myIsUniform[i] = !( fabs(2*d2/myEdgeLength[i]-1.0) > 0.01 || fabs(2*d4/d2-1.0) > 0.01 );
         Handle(Geom_Curve) C3d = BRep_Tool::Curve(myEdge[i],d2,d4);
         myC3dAdaptor[i].Load( C3d, d2,d4 );
@@ -194,12 +195,14 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const StdMeshers_FaceSide*  theSide,
                                          const double                theUFirst,
                                          const double                theULast)
 {
+  myEdge.resize        ( 1 );
+  myEdgeID.resize      ( 1, 0 );
   myC2d.push_back      ( theC2d );
+  myC3dAdaptor.resize  ( 1 );
   myFirst.push_back    ( theUFirst );
   myLast.push_back     ( theULast );
   myNormPar.push_back  ( 1. );
   myIsUniform.push_back( true );
-  myEdgeID.push_back   ( 0 );
   myLength       = 0;
   myProxyMesh    = theSide->myProxyMesh;
   myDefaultPnt2d = *thePnt2d1;
@@ -230,9 +233,11 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const StdMeshers_FaceSide*  theSide,
 //================================================================================
 
 StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec&     theSideNodes,
-                                         const TopoDS_Face& theFace)
+                                         const TopoDS_Face& theFace,
+                                         const TopoDS_Edge& theEdge,
+                                         SMESH_Mesh*        theMesh)
 {
-  myEdge.resize( 1 );
+  myEdge.resize( 1, theEdge );
   myEdgeID.resize( 1, -1 );
   myC2d.resize( 1 );
   myC3dAdaptor.resize( 1 );
@@ -242,6 +247,17 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec&     theSideNodes,
   myIsUniform.resize( 1, 1 );
   myMissingVertexNodes = myIgnoreMediumNodes = false;
   myDefaultPnt2d.SetCoord( 1e100, 1e100 );
+  if ( theMesh ) myProxyMesh.reset( new SMESH_ProxyMesh( *theMesh ));
+  if ( !theEdge.IsNull() )
+  {
+    if ( theMesh ) myEdgeID[0] = theMesh->GetMeshDS()->ShapeToIndex( theEdge );
+    if ( theFace.IsNull() )
+      BRep_Tool::Range( theEdge, myFirst[0], myLast[0] );
+    else
+      myC2d[0] = BRep_Tool::CurveOnSurface( theEdge, theFace, myFirst[0], myLast[0] );
+    if ( theEdge.Orientation() == TopAbs_REVERSED )
+      std::swap( myFirst[0], myLast[0] );
+  }
 
   myFace       = theFace;
   myPoints     = theSideNodes;
@@ -302,15 +318,14 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec&     theSideNodes,
  */
 //================================================================================
 
-const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
-                                                             double constValue) const
+const std::vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
+                                                                  double constValue) const
 {
   if ( myPoints.empty() )
   {
     if ( NbEdges() == 0 ) return myPoints;
 
     StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this );
-    //SMESHDS_Mesh*    meshDS = myProxyMesh->GetMeshDS();
     SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
     SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
     fHelper.SetSubShape( myFace );
@@ -415,24 +430,29 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
       else
       {
         node = VertexNode( iE );
-        while ( !node && iE > 0 )
-          node = VertexNode( --iE );
-        if ( !node )
-          return myPoints;
+        if ( myProxyMesh->GetMesh()->HasModificationsToDiscard() )
+          while ( !node && iE > 1 ) // check intermediate VERTEXes
+            node = VertexNode( --iE );
       }
-      if ( u2node.rbegin()->second == node &&
-           !fHelper.IsRealSeam  ( node->getshapeId() ) &&
-           !fHelper.IsDegenShape( node->getshapeId() ))
-        u2node.erase( --u2node.end() );
+      if ( 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 ));
+        u2node.insert( u2node.end(), make_pair( 1., node ));
+      }
     }
 
     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;
     }
 
@@ -449,25 +469,39 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
       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
@@ -475,7 +509,7 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
         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;
@@ -534,8 +568,8 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::SimulateUVPtStruct(int    nbSeg,
                                                                   bool   isXConst,
                                                                   double constValue) const
 {
-  if ( myFalsePoints.empty() ) {
-
+  if ( myFalsePoints.empty() )
+  {
     if ( NbEdges() == 0 ) return myFalsePoints;
 
     vector<uvPtStruct>* points = const_cast<vector<uvPtStruct>*>( &myFalsePoints );
@@ -543,28 +577,29 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::SimulateUVPtStruct(int    nbSeg,
 
     int EdgeIndex = 0;
     double prevNormPar = 0, paramSize = myNormPar[ EdgeIndex ];
-    for ( size_t i = 0 ; i < myFalsePoints.size(); ++i ) {
+    gp_Pnt2d p;
+    for ( size_t i = 0 ; i < myFalsePoints.size(); ++i )
+    {
       double normPar = double(i) / double(nbSeg);
       UVPtStruct & uvPt = (*points)[i];
       uvPt.node = 0;
       uvPt.x = uvPt.y = uvPt.param = uvPt.normParam = normPar;
       if ( isXConst ) uvPt.x = constValue;
       else            uvPt.y = constValue;
-      if ( myNormPar[ EdgeIndex ] < normPar ) {
+      if ( myNormPar[ EdgeIndex ] < normPar )
+      {
         prevNormPar = myNormPar[ EdgeIndex ];
         ++EdgeIndex;
         paramSize = myNormPar[ EdgeIndex ] - prevNormPar;
       }
       double r = ( normPar - prevNormPar )/ paramSize;
       uvPt.param = myFirst[EdgeIndex] * ( 1 - r ) + myLast[EdgeIndex] * r;
-      if ( !myC2d[ EdgeIndex ].IsNull() ) {
-        gp_Pnt2d p = myC2d[ EdgeIndex ]->Value( uvPt.param );
-        uvPt.u = p.X();
-        uvPt.v = p.Y();
-      }
-      else {
-        uvPt.u = uvPt.v = 1e+100;
-      }
+      if ( !myC2d[ EdgeIndex ].IsNull() )
+        p = myC2d[ EdgeIndex ]->Value( uvPt.param );
+      else
+        p = Value2d( normPar );
+      uvPt.u = p.X();
+      uvPt.v = p.Y();
     }
   }
   return myFalsePoints;