Salome HOME
Cleanup of parallel meshing + documentation
[modules/smesh.git] / src / StdMeshers / StdMeshers_RadialQuadrangle_1D2D.cxx
index 56e73fc770a85e139cb9a5c8e914f5447e696657..a97f274a21506a9910403e66441e7ef234a95b46 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2022  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
@@ -70,7 +70,7 @@ using namespace std;
 
 //=======================================================================
 //function : StdMeshers_RadialQuadrangle_1D2D
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 StdMeshers_RadialQuadrangle_1D2D::StdMeshers_RadialQuadrangle_1D2D(int        hypId,
@@ -103,7 +103,7 @@ StdMeshers_RadialQuadrangle_1D2D::~StdMeshers_RadialQuadrangle_1D2D()
 
 //=======================================================================
 //function : CheckHypothesis
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 bool StdMeshers_RadialQuadrangle_1D2D::CheckHypothesis
@@ -111,7 +111,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::CheckHypothesis
                             const TopoDS_Shape&                  aShape,
                             SMESH_Hypothesis::Hypothesis_Status& aStatus)
 {
-  // check aShape 
+  // check aShape
   myNbLayerHypo = 0;
   myDistributionHypo = 0;
 
@@ -163,38 +163,45 @@ namespace
       static TEdgeMarker theEdgeMarker;
       return &theEdgeMarker;
     }
-    //! Clear face sumbesh if something happens on edges
-    void ProcessEvent(const int          event,
+    //! Clear edge sumbesh if something happens on face
+    void ProcessEvent(const int          /*event*/,
                       const int          eventType,
-                      SMESH_subMesh*     edgeSubMesh,
-                      EventListenerData* data,
+                      SMESH_subMesh*     /*faceSubMesh*/,
+                      EventListenerData* edgesHolder,
                       const SMESH_Hypothesis*  /*hyp*/)
     {
-      if ( data && !data->mySubMeshes.empty() && eventType == SMESH_subMesh::ALGO_EVENT)
+      if ( edgesHolder && eventType == SMESH_subMesh::ALGO_EVENT)
       {
-        ASSERT( data->mySubMeshes.front() != edgeSubMesh );
-        SMESH_subMesh* faceSubMesh = data->mySubMeshes.front();
-        faceSubMesh->ComputeStateEngine( SMESH_subMesh::CLEAN );
+        std::list<SMESH_subMesh*>::iterator smIt = edgesHolder->mySubMeshes.begin();
+        for ( ; smIt != edgesHolder->mySubMeshes.end(); ++smIt )
+        {
+          SMESH_subMesh* edgeSM = *smIt;
+          edgeSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
+        }
       }
     }
-  };
-
-  //================================================================================
-  /*!
-   * \brief Mark an edge as computed by StdMeshers_RadialQuadrangle_1D2D
-   */
-  //================================================================================
-
-  void markEdgeAsComputedByMe(const TopoDS_Edge& edge, SMESH_subMesh* faceSubMesh)
-  {
-    if ( SMESH_subMesh* edgeSM = faceSubMesh->GetFather()->GetSubMeshContaining( edge ))
+    //! Store edge SMESH_subMesh'es computed by the algo
+    static void markEdge( const TopoDS_Edge& edge, SMESH_subMesh* faceSM )
     {
-      if ( !edgeSM->GetEventListenerData( TEdgeMarker::getListener() ))
-        faceSubMesh->SetEventListener( TEdgeMarker::getListener(),
-                                       SMESH_subMeshEventListenerData::MakeData(faceSubMesh),
-                                       edgeSM);
+      if ( SMESH_subMesh* edgeSM = faceSM->GetFather()->GetSubMeshContaining( edge ))
+      {
+        EventListenerData* edgesHolder = faceSM->GetEventListenerData( getListener() );
+        if ( edgesHolder )
+        {
+          std::list<SMESH_subMesh*>::iterator smIt = std::find( edgesHolder->mySubMeshes.begin(),
+                                                                edgesHolder->mySubMeshes.end(),
+                                                                edgeSM );
+          if ( smIt == edgesHolder->mySubMeshes.end() )
+            edgesHolder->mySubMeshes.push_back( edgeSM );
+        }
+        else
+        {
+          edgesHolder = SMESH_subMeshEventListenerData::MakeData( edgeSM );
+          faceSM->SetEventListener( TEdgeMarker::getListener(), edgesHolder, faceSM );
+        }
+      }
     }
-  }
+  };
 
   //================================================================================
   /*!
@@ -219,12 +226,19 @@ namespace
     if ( nbWire > 2 || nbEdgesInWire.front() < 1 ) return 0;
 
     // remove degenerated EDGEs
+    TopTools_MapOfShape degenVV;
     list<TopoDS_Edge>::iterator edge = edges.begin();
     while ( edge != edges.end() )
       if ( SMESH_Algo::isDegenerated( *edge ))
+      {
+        degenVV.Add( SMESH_MesherHelper::IthVertex( 0, *edge ));
+        degenVV.Add( SMESH_MesherHelper::IthVertex( 1, *edge ));
         edge = edges.erase( edge );
+      }
       else
+      {
         ++edge;
+      }
     int nbEdges = edges.size();
 
     // find VERTEXes between continues EDGEs
@@ -257,7 +271,7 @@ namespace
         sideEdges.splice( sideEdges.end(), edges, edges.begin() );
 
       StdMeshers_FaceSidePtr side;
-      if ( aMesh ) 
+      if ( aMesh )
         side = StdMeshers_FaceSide::New( face, sideEdges, aMesh,
                                          /*isFwd=*/true, /*skipMedium=*/ true, helper );
       sides.push_back( side );
@@ -320,12 +334,28 @@ namespace
       double len1 = (++l2i)->first;
       double len2 = (++l2i)->first;
       if ( len1 - len0 > len2 - len1 )
-        deviation2sideInd.insert( make_pair( 0., len2sideInd.begin()->second ));
+        deviation2sideInd.insert( std::make_pair( 0., len2sideInd.begin()->second ));
       else
-        deviation2sideInd.insert( make_pair( 0., len2sideInd.rbegin()->second ));
+        deviation2sideInd.insert( std::make_pair( 0., len2sideInd.rbegin()->second ));
     }
 
-    int iCirc = deviation2sideInd.rbegin()->second; 
+    double minDevi = deviation2sideInd.begin()->first;
+    int   iMinCurv = deviation2sideInd.begin()->second;
+    if ( sides.size() == 3 && degenVV.Size() == 1 &&
+         minDevi / sides[ iMinCurv ]->Length() > 1e-3 )
+    {
+      // a triangle with curved sides and a degenerated EDGE (IPAL54585);
+      // use a side opposite to the degenerated EDGE as an elliptic one
+      for ( size_t iS = 0; iS < sides.size(); ++iS )
+        if ( degenVV.Contains( sides[ iS ]->FirstVertex() ))
+        {
+          deviation2sideInd.clear();
+          deviation2sideInd.insert( std::make_pair( 0.,( iS + 1 ) % sides.size() ));
+          break;
+        }
+    }
+
+    int iCirc = deviation2sideInd.rbegin()->second;
     aCircSide = sides[ iCirc ];
     aLinSide1 = sides[( iCirc + 1 ) % sides.size() ];
     if ( sides.size() > 2 )
@@ -372,9 +402,9 @@ namespace
    */
   //================================================================================
 
-  bool isCornerInsideCircle(const StdMeshers_FaceSidePtr& CircSide,
-                            const StdMeshers_FaceSidePtr& LinSide1,
-                            const StdMeshers_FaceSidePtr& LinSide2)
+  bool isCornerInsideCircle(const StdMeshers_FaceSidePtr& /*CircSide*/,
+                            const StdMeshers_FaceSidePtr& /*LinSide1*/,
+                            const StdMeshers_FaceSidePtr& /*LinSide2*/)
   {
     // if ( CircSide && LinSide1 && LinSide2 )
     // {
@@ -409,7 +439,7 @@ namespace
   {
     // find the center and a point most distant from it
 
-    double maxDist = 0, normPar;
+    double maxDist = 0, normPar = 0;
     gp_XY uv1, uv2;
     for ( int i = 0; i < 32; ++i )
     {
@@ -668,7 +698,7 @@ public:
     return true;
   }
   // -----------------------------------------------------------------------------
-  //! Make mesh on an adge using assigned 1d hyp or default nb of segments
+  //! Make mesh on an edge using assigned 1d hyp or default nb of segments
   bool ComputeCircularEdge( SMESH_Mesh&                   aMesh,
                             const StdMeshers_FaceSidePtr& aSide )
   {
@@ -696,7 +726,7 @@ public:
     return ok;
   }
   // -----------------------------------------------------------------------------
-  //! Make mesh on an adge using assigned 1d hyp or default nb of segments
+  //! Make mesh on an edge using assigned 1d hyp or default nb of segments
   bool EvaluateCircularEdge(SMESH_Mesh&                  aMesh,
                             const StdMeshers_FaceSidePtr aSide,
                             MapShapeNbElems&             aResMap)
@@ -744,18 +774,30 @@ protected:
  * \brief Allow algo to do something after persistent restoration
  * \param subMesh - restored submesh
  *
- * call markEdgeAsComputedByMe()
+ * call TEdgeMarker::markEdge()
  */
 //=======================================================================
 
 void StdMeshers_RadialQuadrangle_1D2D::SubmeshRestored(SMESH_subMesh* faceSubMesh)
 {
   if ( !faceSubMesh->IsEmpty() )
+    SetEventListener( faceSubMesh );
+}
+
+//=======================================================================
+/*!
+ * \brief Sets event listener to a submesh
+ * \param subMesh - submesh where algo is set
+ *
+ * This method is called when a submesh gets HYP_OK algo_state.
+ */
+//=======================================================================
+
+void StdMeshers_RadialQuadrangle_1D2D::SetEventListener(SMESH_subMesh* faceSubMesh)
+{
+  for ( TopExp_Explorer e( faceSubMesh->GetSubShape(), TopAbs_EDGE ); e.More(); e.Next() )
   {
-    for ( TopExp_Explorer e( faceSubMesh->GetSubShape(), TopAbs_EDGE ); e.More(); e.Next() )
-    {
-      markEdgeAsComputedByMe( TopoDS::Edge( e.Current() ), faceSubMesh );
-    }
+    TEdgeMarker::markEdge( TopoDS::Edge( e.Current() ), faceSubMesh );
   }
 }
 
@@ -916,7 +958,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh&         aMesh,
     centerUV   = nodes.back().UV();
   }
   // ------------------------------------------------------------------------------------------
-  else // nbSides == 3 
+  else // nbSides == 3
   {
     // one curve must be a part of ellipse and 2 other curves must be segments of line
 
@@ -963,7 +1005,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh&         aMesh,
 
   list< TopoDS_Edge >::iterator ee = emptyEdges.begin();
   for ( ; ee != emptyEdges.end(); ++ee )
-    markEdgeAsComputedByMe( *ee, aMesh.GetSubMesh( F ));
+    TEdgeMarker::markEdge( *ee, aMesh.GetSubMesh( F ));
 
   circSide->GetUVPtStruct(); // let sides take into account just computed nodes
   linSide1->GetUVPtStruct();
@@ -975,6 +1017,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh&         aMesh,
   quad->side[1] = linSide1;
   quad->side[2] = StdMeshers_FaceSide::New( circSide.get(), centerNode, &centerUV );
   quad->side[3] = linSide2;
+  quad->face    = F;
 
   myQuadList.push_back( quad );
 
@@ -985,6 +1028,12 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh&         aMesh,
   else
     ok = StdMeshers_Quadrangle_2D::computeTriangles( aMesh, F, quad );
 
+  if ( helper.HasDegeneratedEdges() )
+  {
+    StdMeshers_Quadrangle_2D::myNeedSmooth = true;
+    StdMeshers_Quadrangle_2D::smooth( quad );
+  }
+
   StdMeshers_Quadrangle_2D::myHelper = 0;
 
   return ok;
@@ -1033,7 +1082,7 @@ int StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(StdMeshers_FaceSideP
     if ( !TNodeDistributor::GetDistributor(*mesh)->Compute( positions, linSide->Edge(0),
                                                             *curve, f, l, *mesh, hyp1D ))
     {
-      if ( myDistributionHypo ) { // bad hyp assigned 
+      if ( myDistributionHypo ) { // bad hyp assigned
         return error( TNodeDistributor::GetDistributor(*mesh)->GetComputeError() );
       }
       else {
@@ -1041,7 +1090,7 @@ int StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(StdMeshers_FaceSideP
       }
     }
   }
-  
+
   if ( positions.empty() ) // try to use nb of layers
   {
     if ( !nbLayers )
@@ -1083,7 +1132,7 @@ int StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(StdMeshers_FaceSideP
 
 //=======================================================================
 //function : Evaluate
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh&         aMesh,
@@ -1097,8 +1146,8 @@ bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh&         aMesh,
   if( aResMap.count(sm) )
     return false;
 
-  vector<int>& aResVec =
-    aResMap.insert( make_pair(sm, vector<int>(SMDSEntity_Last,0))).first->second;
+  vector<smIdType>& aResVec =
+    aResMap.insert( make_pair(sm, vector<smIdType>(SMDSEntity_Last,0))).first->second;
 
   myHelper = new SMESH_MesherHelper( aMesh );
   myHelper->SetSubShape( aShape );
@@ -1144,7 +1193,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh&         aMesh,
       return false;
   }
   // ------------------------------------------------------------------------------------------
-  else // nbSides == 3 
+  else // nbSides == 3
   {
     if ( !computeLayerPositions(( linSide1->Length() > linSide2->Length() ) ? linSide1 : linSide2,
                                  layerPositions ))
@@ -1155,23 +1204,23 @@ bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh&         aMesh,
   for ( TopExp_Explorer edge( aShape, TopAbs_EDGE ); edge.More() &&  !isQuadratic ; edge.Next() )
   {
     sm = aMesh.GetSubMesh( edge.Current() );
-    vector<int>& nbElems = aResMap[ sm ];
+    vector<smIdType>& nbElems = aResMap[ sm ];
     if ( SMDSEntity_Quad_Edge < (int) nbElems.size() )
       isQuadratic = nbElems[ SMDSEntity_Quad_Edge ];
   }
 
-  int nbCircSegments = 0;
+  smIdType nbCircSegments = 0;
   for ( int iE = 0; iE < circSide->NbEdges(); ++iE )
   {
     sm = aMesh.GetSubMesh( circSide->Edge( iE ));
-    vector<int>& nbElems = aResMap[ sm ];
+    vector<smIdType>& nbElems = aResMap[ sm ];
     if ( SMDSEntity_Quad_Edge < (int) nbElems.size() )
       nbCircSegments += ( nbElems[ SMDSEntity_Edge ] + nbElems[ SMDSEntity_Quad_Edge ]);
   }
-  
-  int nbQuads = nbCircSegments * ( layerPositions.size() - 1 );
-  int nbTria  = nbCircSegments;
-  int nbNodes = ( nbCircSegments - 1 ) * ( layerPositions.size() - 2 );
+
+  smIdType nbQuads = nbCircSegments * ( layerPositions.size() - 1 );
+  smIdType nbTria  = nbCircSegments;
+  smIdType nbNodes = ( nbCircSegments - 1 ) * ( layerPositions.size() - 2 );
   if ( isQuadratic )
   {
     nbNodes += (( nbCircSegments - 1 ) * ( layerPositions.size() - 1 ) + // radial
@@ -1189,7 +1238,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh&         aMesh,
   if ( linSide1 )
   {
     // evaluation for linSides
-    vector<int> aResVec(SMDSEntity_Last, 0);
+    vector<smIdType> aResVec(SMDSEntity_Last, 0);
     if ( isQuadratic ) {
       aResVec[SMDSEntity_Node     ] = 2 * ( layerPositions.size() - 1 ) + 1;
       aResVec[SMDSEntity_Quad_Edge] = layerPositions.size() - 1;
@@ -1230,4 +1279,4 @@ bool StdMeshers_RadialQuadrangle_1D2D::IsApplicable( const TopoDS_Shape & aShape
   }
   if( toCheckAll && nbFoundFaces != 0 ) return true;
   return false;
-};
+}