Salome HOME
23620: EDF 10301 - Completing Extrusion along a path
[modules/smesh.git] / src / StdMeshers / StdMeshers_ViscousLayers2D.cxx
index 013e2d9d94d5f2747d825dc0d68687f8e39f5811..53118b73f70840bc5a0db79bbf3e0242c92d2216 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -30,6 +30,7 @@
 #include "SMDS_SetIterator.hxx"
 #include "SMESHDS_Group.hxx"
 #include "SMESHDS_Hypothesis.hxx"
+#include "SMESHDS_Mesh.hxx"
 #include "SMESH_Algo.hxx"
 #include "SMESH_ComputeError.hxx"
 #include "SMESH_ControlsDef.hxx"
@@ -37,6 +38,7 @@
 #include "SMESH_Group.hxx"
 #include "SMESH_HypoFilter.hxx"
 #include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_ProxyMesh.hxx"
 #include "SMESH_Quadtree.hxx"
@@ -109,14 +111,15 @@ namespace VISCOUS_2D
     // Proxy sub-mesh of an EDGE. It contains nodes in _uvPtStructVec.
     struct _EdgeSubMesh : public SMESH_ProxyMesh::SubMesh
     {
-      _EdgeSubMesh(int index=0): SubMesh(index) {}
+      _EdgeSubMesh(const SMDS_Mesh* mesh, int index=0): SubMesh(mesh,index) {}
       //virtual int NbElements() const { return _elements.size()+1; }
       virtual int NbNodes() const { return Max( 0, _uvPtStructVec.size()-2 ); }
       void SetUVPtStructVec(UVPtStructVec& vec) { _uvPtStructVec.swap( vec ); }
+      UVPtStructVec& GetUVPtStructVec() { return _uvPtStructVec; }
     };
     _ProxyMeshOfFace(const SMESH_Mesh& mesh): SMESH_ProxyMesh(mesh) {}
     _EdgeSubMesh* GetEdgeSubMesh(int ID) { return (_EdgeSubMesh*) getProxySubMesh(ID); }
-    virtual SubMesh* newSubmesh(int index=0) const { return new _EdgeSubMesh(index); }
+    virtual SubMesh* newSubmesh(int index=0) const { return new _EdgeSubMesh( GetMeshDS(), index); }
   };
   //--------------------------------------------------------------------------------
   /*!
@@ -174,7 +177,7 @@ namespace VISCOUS_2D
    */
   struct _Segment
   {
-    const gp_XY* _uv[2];       // poiter to _LayerEdge::_uvIn
+    const gp_XY* _uv[2];       // pointer to _LayerEdge::_uvIn
     int          _indexInLine; // position in _PolyLine
 
     _Segment() {}
@@ -299,6 +302,8 @@ namespace VISCOUS_2D
     double   _D;               // _vec1.Crossed( _vec2 )
     double   _param1, _param2; // intersection param on _seg1 and _seg2
 
+    _SegmentIntersection(): _D(0), _param1(0), _param2(0) {}
+
     bool Compute(const _Segment& seg1, const _Segment& seg2, bool seg2IsRay = false )
     {
       // !!! If seg2IsRay, returns true at any _param2 !!!
@@ -497,8 +502,8 @@ namespace VISCOUS_2D
 //================================================================================
 // StdMeshers_ViscousLayers hypothesis
 //
-StdMeshers_ViscousLayers2D::StdMeshers_ViscousLayers2D(int hypId, int studyId, SMESH_Gen* gen)
-  :StdMeshers_ViscousLayers(hypId, studyId, gen)
+StdMeshers_ViscousLayers2D::StdMeshers_ViscousLayers2D(int hypId, SMESH_Gen* gen)
+  :StdMeshers_ViscousLayers(hypId, gen)
 {
   _name = StdMeshers_ViscousLayers2D::GetHypType();
   _param_algo_dim = -2; // auxiliary hyp used by 2D algos
@@ -515,29 +520,53 @@ SMESH_ProxyMesh::Ptr
 StdMeshers_ViscousLayers2D::Compute(SMESH_Mesh&        theMesh,
                                     const TopoDS_Face& theFace)
 {
-  SMESH_ProxyMesh::Ptr pm;
-
+  using namespace VISCOUS_2D;
   vector< const StdMeshers_ViscousLayers2D* > hyps;
   vector< TopoDS_Shape >                      hypShapes;
-  if ( VISCOUS_2D::findHyps( theMesh, theFace, hyps, hypShapes ))
+
+  SMESH_ProxyMesh::Ptr pm = _ProxyMeshHolder::FindProxyMeshOfFace( theFace, theMesh );
+  if ( !pm )
   {
-    VISCOUS_2D::_ViscousBuilder2D builder( theMesh, theFace, hyps, hypShapes );
-    pm = builder.Compute();
-    SMESH_ComputeErrorPtr error = builder.GetError();
-    if ( error && !error->IsOK() )
-      theMesh.GetSubMesh( theFace )->GetComputeError() = error;
-    else if ( !pm )
+    if ( findHyps( theMesh, theFace, hyps, hypShapes ))
+    {
+      VISCOUS_2D::_ViscousBuilder2D builder( theMesh, theFace, hyps, hypShapes );
+      pm = builder.Compute();
+      SMESH_ComputeErrorPtr error = builder.GetError();
+      if ( error && !error->IsOK() )
+        theMesh.GetSubMesh( theFace )->GetComputeError() = error;
+      else if ( !pm )
+        pm.reset( new SMESH_ProxyMesh( theMesh ));
+      if ( getenv("__ONLY__VL2D__"))
+        pm.reset();
+    }
+    else
+    {
       pm.reset( new SMESH_ProxyMesh( theMesh ));
-    if ( getenv("__ONLY__VL2D__"))
-      pm.reset();
-  }
-  else
-  {
-    pm.reset( new SMESH_ProxyMesh( theMesh ));
+    }
   }
   return pm;
 }
 // --------------------------------------------------------------------------------
+void StdMeshers_ViscousLayers2D::SetProxyMeshOfEdge( const StdMeshers_FaceSide& edgeNodes )
+{
+  using namespace VISCOUS_2D;
+  SMESH_ProxyMesh::Ptr pm =
+    _ProxyMeshHolder::FindProxyMeshOfFace( edgeNodes.Face(), *edgeNodes.GetMesh() );
+  if ( !pm ) {
+    _ProxyMeshOfFace* proxyMeshOfFace = new _ProxyMeshOfFace( *edgeNodes.GetMesh() );
+    pm.reset( proxyMeshOfFace );
+    new _ProxyMeshHolder( edgeNodes.Face(), pm );
+  }
+  _ProxyMeshOfFace*  proxyMeshOfFace = static_cast<_ProxyMeshOfFace*>( pm.get() );
+  _ProxyMeshOfFace::_EdgeSubMesh* sm = proxyMeshOfFace->GetEdgeSubMesh( edgeNodes.EdgeID(0) );
+  sm->GetUVPtStructVec() = edgeNodes.GetUVPtStruct();
+}
+// --------------------------------------------------------------------------------
+bool StdMeshers_ViscousLayers2D::HasProxyMesh( const TopoDS_Face& face, SMESH_Mesh& mesh )
+{
+  return VISCOUS_2D::_ProxyMeshHolder::FindProxyMeshOfFace( face, mesh ).get();
+}
+// --------------------------------------------------------------------------------
 SMESH_ComputeErrorPtr
 StdMeshers_ViscousLayers2D::CheckHypothesis(SMESH_Mesh&                          theMesh,
                                             const TopoDS_Shape&                  theShape,
@@ -557,7 +586,7 @@ StdMeshers_ViscousLayers2D::CheckHypothesis(SMESH_Mesh&
       VISCOUS_2D::_ViscousBuilder2D builder( theMesh, face, hyps, hypShapes );
       builder._faceSideVec =
         StdMeshers_FaceSide::GetFaceWires( face, theMesh, true, error,
-                                           SMESH_ProxyMesh::Ptr(),
+                                           NULL, SMESH_ProxyMesh::Ptr(),
                                            /*theCheckVertexNodes=*/false);
       if ( error->IsOK() && !builder.findEdgesWithLayers())
       {
@@ -572,7 +601,7 @@ StdMeshers_ViscousLayers2D::CheckHypothesis(SMESH_Mesh&
 // --------------------------------------------------------------------------------
 void StdMeshers_ViscousLayers2D::RestoreListeners() const
 {
-  StudyContextStruct* sc = _gen->GetStudyContext( _studyId );
+  StudyContextStruct* sc = _gen->GetStudyContext();
   std::map < int, SMESH_Mesh * >::iterator i_smesh = sc->mapMesh.begin();
   for ( ; i_smesh != sc->mapMesh.end(); ++i_smesh )
   {
@@ -658,7 +687,7 @@ bool _ViscousBuilder2D::error(const string& text )
 
 SMESH_ProxyMesh::Ptr _ViscousBuilder2D::Compute()
 {
-  _faceSideVec = StdMeshers_FaceSide::GetFaceWires( _face, *_mesh, true, _error);
+  _faceSideVec = StdMeshers_FaceSide::GetFaceWires( _face, *_mesh, true, _error, &_helper );
 
   if ( !_error->IsOK() )
     return _proxyMesh;
@@ -817,7 +846,7 @@ bool _ViscousBuilder2D::findEdgesWithLayers()
                   {
                     hasVL = false;
                     for ( hyp = allHyps.begin(); hyp != allHyps.end() && !hasVL; ++hyp )
-                      if ( viscHyp = dynamic_cast<const THypVL*>( *hyp ))
+                      if (( viscHyp = dynamic_cast<const THypVL*>( *hyp )))
                         hasVL = viscHyp->IsShapeWithLayers( neighbourID );
                   }
                   if ( !hasVL )
@@ -1235,7 +1264,7 @@ void _ViscousBuilder2D::adjustCommonEdge( _PolyLine& LL, _PolyLine& LR )
           if ( isR )
             LR._lEdges.erase( LR._lEdges.begin()+1, eIt );
           else
-            LL._lEdges.erase( eIt, --LL._lEdges.end() );
+            LL._lEdges.erase( eIt+1, --LL._lEdges.end() );
           // eIt = isR ? L._lEdges.begin()+1 : L._lEdges.end()-2;
           // for ( size_t i = 1; i < iLE; ++i, eIt += dIt )
           //   eIt->_isBlocked = true;
@@ -1290,7 +1319,7 @@ void _ViscousBuilder2D::setLayerEdgeData( _LayerEdge&                 lEdge,
     faceProj->Perform( p );
     if ( !faceProj->IsDone() || faceProj->NbPoints() < 1 )
       return setLayerEdgeData( lEdge, u, pcurve, curve, p, reverse, NULL );
-    Quantity_Parameter U,V;
+    Standard_Real U,V;
     faceProj->LowerDistanceParameters(U,V);
     lEdge._normal2D.SetCoord( U - uv.X(), V - uv.Y() );
     lEdge._normal2D.Normalize();
@@ -1438,7 +1467,7 @@ bool _ViscousBuilder2D::inflate()
       _PolyLine::TEdgeIterator eIt = isR ? L._lEdges.end()-1 : L._lEdges.begin();
       if ( eIt->_length2D == 0 ) continue;
       _Segment seg1( eIt->_uvOut, eIt->_uvIn );
-      for ( eIt += deltaIt; nbRemove < L._lEdges.size()-1; eIt += deltaIt )
+      for ( eIt += deltaIt; nbRemove < (int)L._lEdges.size()-1; eIt += deltaIt )
       {
         _Segment seg2( eIt->_uvOut, eIt->_uvIn );
         if ( !intersection.Compute( seg1, seg2 ))
@@ -1446,7 +1475,7 @@ bool _ViscousBuilder2D::inflate()
         ++nbRemove;
       }
       if ( nbRemove > 0 ) {
-        if ( nbRemove == L._lEdges.size()-1 ) // 1st and last _LayerEdge's intersect
+        if ( nbRemove == (int)L._lEdges.size()-1 ) // 1st and last _LayerEdge's intersect
         {
           --nbRemove;
           _LayerEdge& L0 = L._lEdges.front();
@@ -1716,11 +1745,13 @@ bool _ViscousBuilder2D::shrink()
         }
       } // loop on FACEs sharing E
 
+    // Check if L is an already shrinked seam
+    if ( adjFace.IsNull() && _helper.IsRealSeam( edgeID ))
+      if ( L._wire->Edge( L._edgeInd ).Orientation() == TopAbs_FORWARD )
+        continue;
     // Commented as a case with a seam EDGE (issue 0052461) is hard to support
     // because SMESH_ProxyMesh can't hold different sub-meshes for two
     // 2D representations of the seam. But such a case is not a real practice one.
-    // Check if L is an already shrinked seam
-    // if ( adjFace.IsNull() && _helper.IsRealSeam( edgeID ))
     // {
     //   for ( int iL2 = iL1-1; iL2 > -1; --iL2 )
     //   {
@@ -1794,7 +1825,7 @@ bool _ViscousBuilder2D::shrink()
     //  x-x-x-x-----x-----x----
     //  | | | |  e1    e2    e3
 
-    int isRShrinkedForAdjacent;
+    int isRShrinkedForAdjacent = 0;
     UVPtStructVec nodeDataForAdjacent;
     for ( int isR = 0; isR < 2; ++isR )
     {
@@ -1968,7 +1999,7 @@ bool _ViscousBuilder2D::shrink()
         throw SALOME_Exception(SMESH_Comment("ViscousBuilder2D: not SMDS_TOP_EDGE node position: ")
                                << oldNode->GetPosition()->GetTypeOfPosition()
                                << " of node " << oldNode->GetID());
-      SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( oldNode->GetPosition() );
+      SMDS_EdgePositionPtr pos = oldNode->GetPosition();
       pos->SetUParameter( nodeDataVec[iP].param );
 
       gp_Pnt newP = curve.Value( nodeDataVec[iP].param );
@@ -2131,7 +2162,7 @@ bool _ViscousBuilder2D::refine()
   // store a proxyMesh in a sub-mesh
   // make faces on each _PolyLine
   vector< double > layersHeight;
-  double prevLen2D = -1;
+  //double prevLen2D = -1;
   for ( size_t iL = 0; iL < _polyLineVec.size(); ++iL )
   {
     _PolyLine& L = _polyLineVec[ iL ];
@@ -2157,7 +2188,7 @@ bool _ViscousBuilder2D::refine()
     vector< double > segLen( L._lEdges.size() );
     segLen[0] = 0.0;
 
-    // check if length modification is usefull: look for _LayerEdge's
+    // check if length modification is useful: look for _LayerEdge's
     // with length limited due to collisions
     bool lenLimited = false;
     for ( size_t iLE = 1; ( iLE < L._lEdges.size()-1 && !lenLimited ); ++iLE )
@@ -2410,6 +2441,19 @@ bool _ViscousBuilder2D::refine()
     nodeDataVec.front().param = L._wire->FirstU( L._edgeInd );
     nodeDataVec.back() .param = L._wire->LastU ( L._edgeInd );
 
+    if (( nodeDataVec[0].node == nodeDataVec.back().node ) &&
+        ( _helper.GetPeriodicIndex() == 1 || _helper.GetPeriodicIndex() == 2 )) // closed EDGE
+    {
+      const int iCoord = _helper.GetPeriodicIndex();
+      gp_XY uv = nodeDataVec[0].UV();
+      uv.SetCoord( iCoord, L._lEdges[0]._uvOut.Coord( iCoord ));
+      nodeDataVec[0].SetUV( uv );
+
+      uv = nodeDataVec.back().UV();
+      uv.SetCoord( iCoord, L._lEdges.back()._uvOut.Coord( iCoord ));
+      nodeDataVec.back().SetUV( uv );
+    }
+
     _ProxyMeshOfFace::_EdgeSubMesh* edgeSM
       = getProxyMesh()->GetEdgeSubMesh( L._wire->EdgeID( L._edgeInd ));
     edgeSM->SetUVPtStructVec( nodeDataVec );
@@ -2669,7 +2713,7 @@ _SegmentTree::box_type* _SegmentTree::buildRootBox()
 
 void _SegmentTree::buildChildrenData()
 {
-  for ( int i = 0; i < _segments.size(); ++i )
+  for ( size_t i = 0; i < _segments.size(); ++i )
     for (int j = 0; j < nbChildren(); j++)
       if ( !myChildren[j]->getBox()->IsOut( *_segments[i]._seg->_uv[0],
                                             *_segments[i]._seg->_uv[1] ))
@@ -2680,7 +2724,7 @@ void _SegmentTree::buildChildrenData()
   for (int j = 0; j < nbChildren(); j++)
   {
     _SegmentTree* child = static_cast<_SegmentTree*>( myChildren[j]);
-    child->myIsLeaf = ( child->_segments.size() <= maxNbSegInLeaf() );
+    child->myIsLeaf = ((int) child->_segments.size() <= maxNbSegInLeaf() );
   }
 }
 
@@ -2698,7 +2742,7 @@ void _SegmentTree::GetSegmentsNear( const _Segment&            seg,
 
   if ( isLeaf() )
   {
-    for ( int i = 0; i < _segments.size(); ++i )
+    for ( size_t i = 0; i < _segments.size(); ++i )
       if ( !_segments[i].IsOut( seg ))
         found.push_back( _segments[i]._seg );
   }
@@ -2724,7 +2768,7 @@ void _SegmentTree::GetSegmentsNear( const gp_Ax2d&             ray,
 
   if ( isLeaf() )
   {
-    for ( int i = 0; i < _segments.size(); ++i )
+    for ( size_t i = 0; i < _segments.size(); ++i )
       if ( !_segments[i].IsOut( ray ))
         found.push_back( _segments[i]._seg );
   }