Salome HOME
Fix regression SALOME_TESTS/Grids/smesh/viscous_layers_00/A3 - too thin VL
[modules/smesh.git] / src / StdMeshers / StdMeshers_ViscousLayers.cxx
index 0c40b47438c6ccf930cbf9e6aed0dfbfdd3ae30b..0dd1abad9f018ae80e65fcb52662e62ed80e797e 100644 (file)
@@ -457,7 +457,7 @@ namespace VISCOUS_3D
     void SmoothPos( const vector< double >& segLen, const double tol );
     int  Smooth(const int step, const bool isConcaveFace, bool findBest);
     int  Smooth(const int step, bool findBest, vector< _LayerEdge* >& toSmooth );
-    int  CheckNeiborsOnBoundary(vector< _LayerEdge* >* badNeibors = 0 );
+    int  CheckNeiborsOnBoundary(vector< _LayerEdge* >* badNeibors = 0, bool * needSmooth = 0 );
     void SmoothWoCheck();
     bool SmoothOnEdge(Handle(ShapeAnalysis_Surface)& surface,
                       const TopoDS_Face&             F,
@@ -4670,8 +4670,8 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
       _LayerEdge*      edge = eos._edges[i];
       if ( edge->_nodes.size() < 2 ) continue;
       SMESH_TNodeXYZ tgtXYZ = edge->_nodes.back();
-      //const gp_XYZ& prevXYZ = edge->PrevCheckPos();
-      const gp_XYZ& prevXYZ = edge->PrevPos();
+      const gp_XYZ& prevXYZ = edge->PrevCheckPos();
+      //const gp_XYZ& prevXYZ = edge->PrevPos();
       for ( size_t j = 0; j < edge->_simplices.size(); ++j )
         if ( !edge->_simplices[j].IsForward( &prevXYZ, &tgtXYZ, vol ))
         {
@@ -4849,16 +4849,30 @@ int _ViscousBuilder::invalidateBadSmooth( _SolidData&               data,
   data.UnmarkEdges();
 
   double vol;
+  //size_t iniNbBad = badSmooEdges.size();
   for ( size_t i = 0; i < badSmooEdges.size(); ++i )
   {
     _LayerEdge* edge = badSmooEdges[i];
     if ( edge->NbSteps() < 2 || edge->Is( _LayerEdge::MARKED ))
       continue;
+
     _EdgesOnShape* eos = data.GetShapeEdges( edge );
     edge->InvalidateStep( edge->NbSteps(), *eos, /*restoreLength=*/true );
     edge->Block( data );
     edge->Set( _LayerEdge::MARKED );
 
+    // look for _LayerEdge's of bad _simplices
+    SMESH_TNodeXYZ tgtXYZ = edge->_nodes.back();
+    const gp_XYZ& prevXYZ = edge->PrevCheckPos();
+    for ( size_t j = 0; j < edge->_simplices.size(); ++j )
+    {
+      if ( edge->_simplices[j].IsForward( &prevXYZ, &tgtXYZ, vol ))
+        continue;
+      for ( size_t iN = 0; iN < edge->_neibors.size(); ++iN )
+        if ( edge->_simplices[j].Includes( edge->_neibors[iN]->_nodes.back() ))
+          badSmooEdges.push_back( edge->_neibors[iN] );
+    }
+
     if ( eos->ShapeType() == TopAbs_VERTEX )
     {
       // re-smooth on analytical EDGEs
@@ -4874,20 +4888,12 @@ int _ViscousBuilder::invalidateBadSmooth( _SolidData&               data,
             }
             eoe->_edgeSmoother->Perform( data, surface, F, helper );
           }
-    }
 
-    // look for _LayerEdge's of bad _simplices
-    SMESH_TNodeXYZ tgtXYZ = edge->_nodes.back();
-    const gp_XYZ& prevXYZ = edge->PrevCheckPos();
-    for ( size_t j = 0; j < edge->_simplices.size(); ++j )
-    {
-      if ( edge->_simplices[j].IsForward( &prevXYZ, &tgtXYZ, vol ))
-        continue;
-      for ( size_t iN = 0; iN < edge->_neibors.size(); ++iN )
-        if ( edge->_simplices[j].Includes( edge->_neibors[iN]->_nodes.back() ))
-          badSmooEdges.push_back( edge->_neibors[iN] );
     }
-  }
+  } // loop on badSmooEdges
+
+
+  // check result of invalidation
 
   int badNb = 0;
   for ( size_t iEOS = 0; iEOS < eosC1.size(); ++iEOS )
@@ -5153,8 +5159,6 @@ bool _Smoother1D::smoothAnalyticEdge( _SolidData&                    data,
       gp_XYZ newPos;
       for ( size_t i = iFrom; i < iTo; ++i )
       {
-        if ( _eos._edges[i]->Is( _LayerEdge::BLOCKED )) continue;
-
         _LayerEdge*       edge = _eos._edges[i];
         SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( edge->_nodes.back() );
         newPos = p0 * ( 1. - _leParams[i] ) + p1 * _leParams[i];
@@ -5167,6 +5171,14 @@ bool _Smoother1D::smoothAnalyticEdge( _SolidData&                    data,
                              lineDir * ( curPos - pSrc0 ));
           newPos = curPos + lineDir * shift / lineDir.SquareModulus();
         }
+        if ( _eos._edges[i]->Is( _LayerEdge::BLOCKED ))
+        {
+          SMESH_TNodeXYZ pSrc( edge->_nodes[0] );
+          double curThick = pSrc.SquareDistance( tgtNode );
+          double newThink = ( pSrc - newPos ).SquareModulus();
+          if ( newThink > curThick )
+            continue;
+        }
         edge->_pos.back() = newPos;
         tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
         dumpMove( tgtNode );
@@ -7459,7 +7471,7 @@ void _LayerEdge::SmoothWoCheck()
  */
 //================================================================================
 
-int _LayerEdge::CheckNeiborsOnBoundary( vector< _LayerEdge* >* badNeibors )
+int _LayerEdge::CheckNeiborsOnBoundary( vector< _LayerEdge* >* badNeibors, bool * needSmooth )
 {
   if ( ! Is( NEAR_BOUNDARY ))
     return 0;
@@ -7471,6 +7483,9 @@ int _LayerEdge::CheckNeiborsOnBoundary( vector< _LayerEdge* >* badNeibors )
     _LayerEdge* eN = _neibors[iN];
     if ( eN->_nodes[0]->getshapeId() == _nodes[0]->getshapeId() )
       continue;
+    if ( needSmooth )
+      *needSmooth |= ( eN->Is( _LayerEdge::BLOCKED ) || eN->Is( _LayerEdge::NORMAL_UPDATED ));
+
     SMESH_TNodeXYZ curPosN ( eN->_nodes.back() );
     SMESH_TNodeXYZ prevPosN( eN->_nodes[0] );
     for ( size_t i = 0; i < eN->_simplices.size(); ++i )
@@ -7506,7 +7521,7 @@ int _LayerEdge::CheckNeiborsOnBoundary( vector< _LayerEdge* >* badNeibors )
 
 int _LayerEdge::Smooth(const int step, bool findBest, vector< _LayerEdge* >& toSmooth )
 {
-  if ( !Is( MOVED ) || Is( SMOOTHED ))
+  if ( !Is( MOVED ) || Is( SMOOTHED ) || Is( BLOCKED ))
     return 0; // shape of simplices not changed
   if ( _simplices.size() < 2 )
     return 0; // _LayerEdge inflated along EDGE or FACE
@@ -7527,13 +7542,14 @@ int _LayerEdge::Smooth(const int step, bool findBest, vector< _LayerEdge* >& toS
   }
   int nbBad = _simplices.size() - nbOkBefore;
 
+  bool bndNeedSmooth = false;
   if ( nbBad == 0 )
-    nbBad = CheckNeiborsOnBoundary();
+    nbBad = CheckNeiborsOnBoundary( 0, & bndNeedSmooth );
   if ( nbBad > 0 )
     Set( DISTORTED );
 
   // evaluate min angle
-  if ( nbBad == 0 && !findBest )
+  if ( nbBad == 0 && !findBest && !bndNeedSmooth )
   {
     size_t nbGoodAngles = _simplices.size();
     double angle;
@@ -8587,7 +8603,9 @@ void _LayerEdge::Block( _SolidData& data )
         if ( neibor->_maxLen < neibor->_len )
         {
           _EdgesOnShape* eos = data.GetShapeEdges( neibor );
-          neibor->InvalidateStep( neibor->NbSteps(), *eos, /*restoreLength=*/true );
+          while ( neibor->_len > neibor->_maxLen &&
+                  neibor->NbSteps() > 1 )
+            neibor->InvalidateStep( neibor->NbSteps(), *eos, /*restoreLength=*/true );
           neibor->SetNewLength( neibor->_maxLen, *eos, data.GetHelper() );
         }
         queue.push( neibor );
@@ -8635,7 +8653,9 @@ void _LayerEdge::InvalidateStep( size_t curStep, const _EdgesOnShape& eos, bool
     dumpMove( n );
 
     if ( restoreLength )
+    {
       _len -= ( nXYZ.XYZ() - curXYZ ).Modulus() / _lenFactor;
+    }
   }
 }
 
@@ -8830,7 +8850,12 @@ bool _ViscousBuilder::refine(_SolidData& data)
           {
             swapped = false;
             for ( size_t j = 1; j < edge._pos.size(); ++j )
-              if ( segLen[j] < segLen[j-1] )
+              if ( segLen[j] > segLen.back() )
+              {
+                segLen[j]    = segLen[j-1];
+                edge._pos[j] = edge._pos[j-1];
+              }
+              else if ( segLen[j] < segLen[j-1] )
               {
                 std::swap( segLen[j], segLen[j-1] );
                 std::swap( edge._pos[j], edge._pos[j-1] );