]> SALOME platform Git repositories - modules/smesh.git/blobdiff - src/StdMeshers/StdMeshers_Prism_3D.cxx
Salome HOME
fix failure of non-regression test SMESH_TEST/Grids/smesh/imps8/I1
[modules/smesh.git] / src / StdMeshers / StdMeshers_Prism_3D.cxx
index ee33b97933ddc105b7cfbd142648ef5b9a951b94..6584b16652576dabb3e1e993186a55e764e716dc 100644 (file)
@@ -69,8 +69,9 @@ using namespace std;
 // cout << msg << " ("<< p.X() << "; " <<p.Y() << "; " <<p.Z() << ") " <<endl;\
 // }
 
-typedef StdMeshers_ProjectionUtils TAssocTool;
-typedef SMESH_Comment              TCom;
+namespace TAssocTool = StdMeshers_ProjectionUtils;
+
+typedef SMESH_Comment TCom;
 
 enum { ID_BOT_FACE = SMESH_Block::ID_Fxy0,
        ID_TOP_FACE = SMESH_Block::ID_Fxy1,
@@ -89,18 +90,21 @@ namespace {
       : StdMeshers_Quadrangle_2D( gen->GetANewId(), studyId, gen)
     {
     }
-    static StdMeshers_Quadrangle_2D* instance( SMESH_Algo* fatherAlgo,
-                                               SMESH_Mesh* mesh=0)
+    static StdMeshers_Quadrangle_2D* instance( SMESH_Algo*         fatherAlgo,
+                                               SMESH_MesherHelper* helper=0)
     {
       static TQuadrangleAlgo* algo = new TQuadrangleAlgo( fatherAlgo->GetStudyId(),
                                                           fatherAlgo->GetGen() );
-      if ( mesh &&
+      if ( helper &&
            algo->myProxyMesh &&
-           algo->myProxyMesh->GetMesh() != mesh )
-        algo->myProxyMesh.reset( new SMESH_ProxyMesh( *mesh ));
+           algo->myProxyMesh->GetMesh() != helper->GetMesh() )
+        algo->myProxyMesh.reset( new SMESH_ProxyMesh( *helper->GetMesh() ));
 
       algo->myQuadStruct.reset();
 
+      if ( helper )
+        algo->_quadraticMesh = helper->GetIsQuadratic();
+
       return algo;
     }
   };
@@ -454,19 +458,11 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
   if ( nbSolids < 1 )
     return true;
 
-  Prism_3D::TPrismTopo prism;
-
-  if ( nbSolids == 1 )
-  {
-    return ( initPrism( prism, TopExp_Explorer( theShape, TopAbs_SOLID ).Current() ) &&
-             compute( prism ));
-  }
-
   TopTools_IndexedDataMapOfShapeListOfShape faceToSolids;
   TopExp::MapShapesAndAncestors( theShape, TopAbs_FACE, TopAbs_SOLID, faceToSolids );
 
   // look for meshed FACEs ("source" FACEs) that must be prism bottoms
-  list< TopoDS_Face > meshedFaces;//, notQuadMeshedFaces, notQuadFaces;
+  list< TopoDS_Face > meshedFaces, notQuadMeshedFaces, notQuadFaces;
   const bool meshHasQuads = ( theMesh.NbQuadrangles() > 0 );
   for ( int iF = 1; iF < faceToSolids.Extent(); ++iF )
   {
@@ -476,17 +472,33 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
     {
       if ( !meshHasQuads ||
            !helper.IsSameElemGeometry( faceSM->GetSubMeshDS(), SMDSGeom_QUADRANGLE ) ||
-           !helper.IsStructured( faceSM ))
-        // notQuadMeshedFaces are of higher priority
+           !helper.IsStructured( faceSM )
+           )
+        notQuadMeshedFaces.push_front( face );
+      else if ( myHelper->Count( face, TopAbs_EDGE, /*ignoreSame=*/false ) != 4 )
         meshedFaces.push_front( face );
       else
         meshedFaces.push_back( face );
     }
+    else if ( myHelper->Count( face, TopAbs_EDGE, /*ignoreSame=*/false ) != 4 )
+    {
+      notQuadFaces.push_back( face );
+    }
   }
-  //meshedFaces.splice( meshedFaces.begin(), notQuadMeshedFaces );
+  // notQuadFaces are of medium priority, put them before ordinary meshed faces
+  meshedFaces.splice( meshedFaces.begin(), notQuadFaces );
+  // notQuadMeshedFaces are of highest priority, put them before notQuadFaces
+  meshedFaces.splice( meshedFaces.begin(), notQuadMeshedFaces );
 
-  if ( meshedFaces.empty() )
-    return error( COMPERR_BAD_INPUT_MESH, "No meshed source faces found" );
+  Prism_3D::TPrismTopo prism;
+
+  if ( nbSolids == 1 )
+  {
+    if ( !meshedFaces.empty() )
+      prism.myBottom = meshedFaces.front();
+    return ( initPrism( prism, TopExp_Explorer( theShape, TopAbs_SOLID ).Current() ) &&
+             compute( prism ));
+  }
 
   TopTools_MapOfShape meshedSolids;
   list< Prism_3D::TPrismTopo > meshedPrism;
@@ -502,26 +514,29 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
     {
       TopoDS_Face face = meshedFaces.front();
       meshedFaces.pop_front();
-      solidIt.Initialize( faceToSolids.FindFromKey( face ));
-      for ( ; solidIt.More(); solidIt.Next() )
+      TopTools_ListOfShape& solidList = faceToSolids.ChangeFromKey( face );
+      while ( !solidList.IsEmpty() )
       {
-        const TopoDS_Shape& solid = solidIt.Value();
-        if ( !meshedSolids.Add( solid ))
-          continue; // already computed prism
-
-        prism.Clear();
-        prism.myBottom = face;
-        if ( !initPrism( prism, solid ) ||
-             !compute( prism ))
-          return false;
+        TopoDS_Shape solid = solidList.First();
+        solidList.RemoveFirst();
+        if ( meshedSolids.Add( solid ))
+        {
+          prism.Clear();
+          prism.myBottom = face;
+          if ( !initPrism( prism, solid ) ||
+               !compute( prism ))
+            return false;
 
-        meshedFaces.push_front( prism.myTop );
-        meshedPrism.push_back( prism );
+          meshedFaces.push_front( prism.myTop );
+          meshedPrism.push_back( prism );
+        }
       }
     }
     if ( meshedSolids.Extent() == nbSolids )
       break;
 
+    // below in the loop we try to find source FACEs somehow
+
     // project mesh from source FACEs of computed prisms to
     // prisms sharing wall FACEs
     list< Prism_3D::TPrismTopo >::iterator prismIt = meshedPrism.begin();
@@ -533,13 +548,15 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
         for ( ; wQuad != prismIt->myWallQuads[iW].end(); ++ wQuad )
         {
           const TopoDS_Face& wFace = (*wQuad)->face;
-          solidIt.Initialize( faceToSolids.FindFromKey( wFace ));
-          for ( ; solidIt.More(); solidIt.Next() )
+          TopTools_ListOfShape& solidList = faceToSolids.ChangeFromKey( wFace );
+          solidIt.Initialize( solidList );
+          while ( solidIt.More() )
           {
             const TopoDS_Shape& solid = solidIt.Value();
-            if ( meshedSolids.Contains( solid ))
+            if ( meshedSolids.Contains( solid )) {
+              solidList.Remove( solidIt );
               continue; // already computed prism
-
+            }
             // find a source FACE of the SOLID: it's a FACE sharing a bottom EDGE with wFace
             const TopoDS_Edge& wEdge = (*wQuad)->side[ QUAD_TOP_SIDE ]->Edge(0);
             PShapeIteratorPtr faceIt = myHelper->GetAncestors( wEdge, *myHelper->GetMesh(),
@@ -567,6 +584,10 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
             }
             mySetErrorToSM = true;
             InitComputeError();
+            if ( meshedSolids.Contains( solid ))
+              solidList.Remove( solidIt );
+            else
+              solidIt.Next();
           }
         }
       }
@@ -574,9 +595,60 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
         break; // to compute prisms with avident sources
     }
 
+    // find FACEs with local 1D hyps, which has to be computed by now,
+    // or at least any computed FACEs
+    for ( int iF = 1; ( meshedFaces.empty() && iF < faceToSolids.Extent() ); ++iF )
+    {
+      const TopoDS_Face&               face = TopoDS::Face( faceToSolids.FindKey( iF ));
+      const TopTools_ListOfShape& solidList = faceToSolids.FindFromKey( face );
+      if ( solidList.IsEmpty() ) continue;
+      SMESH_subMesh*                 faceSM = theMesh.GetSubMesh( face );
+      if ( !faceSM->IsEmpty() )
+      {
+        meshedFaces.push_back( face ); // lower priority
+      }
+      else
+      {
+        bool allSubMeComputed = true;
+        SMESH_subMeshIteratorPtr smIt = faceSM->getDependsOnIterator(false,true);
+        while ( smIt->more() && allSubMeComputed )
+          allSubMeComputed = smIt->next()->IsMeshComputed();
+        if ( allSubMeComputed )
+        {
+          faceSM->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+          if ( !faceSM->IsEmpty() )
+            meshedFaces.push_front( face ); // higher priority
+          else
+            faceSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+        }
+      }
+    }
+
+
     // TODO. there are other ways to find out the source FACE:
     // propagation, topological similarity, ect.
 
+    // simply try to mesh all not meshed SOLIDs
+    if ( meshedFaces.empty() )
+    {
+      for ( TopExp_Explorer solid( theShape, TopAbs_SOLID ); solid.More(); solid.Next() )
+      {
+        mySetErrorToSM = false;
+        prism.Clear();
+        if ( !meshedSolids.Contains( solid.Current() ) &&
+             initPrism( prism, solid.Current() ))
+        {
+          mySetErrorToSM = true;
+          if ( !compute( prism ))
+            return false;
+          meshedFaces.push_front( prism.myTop );
+          meshedFaces.push_front( prism.myBottom );
+          meshedPrism.push_back( prism );
+          meshedSolids.Add( solid.Current() );
+        }
+        mySetErrorToSM = true;
+      }
+    }
 
     if ( meshedFaces.empty() ) // set same error to 10 not-computed solids
     {
@@ -591,7 +663,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
           SMESH_subMesh* sm = theMesh.GetSubMesh( solid.Current() );
           sm->GetComputeError() = err;
         }
-      return false;
+      return error( err );
     }
   }
   return true;
@@ -610,7 +682,7 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
 
   SMESH_Mesh* mesh = myHelper->GetMesh();
 
-  StdMeshers_Quadrangle_2D* quadAlgo = TQuadrangleAlgo::instance( this, mesh );
+  StdMeshers_Quadrangle_2D* quadAlgo = TQuadrangleAlgo::instance( this, myHelper );
 
   TopTools_MapOfShape faceMap;
   TopTools_IndexedDataMapOfShapeListOfShape edgeToFaces;   
@@ -666,7 +738,7 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
   // -------------------------
 
   // Compose a vector of indixes of right neighbour FACE for each wall FACE
-  // that is not so evident in case of several WIREs
+  // that is not so evident in case of several WIREs in the bottom FACE
   thePrism.myRightQuadIndex.clear();
   for ( size_t i = 0; i < thePrism.myWallQuads.size(); ++i )
     thePrism.myRightQuadIndex.push_back( i+1 );
@@ -817,7 +889,7 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
 
   // try to use transformation (issue 0020680)
   vector<gp_Trsf> trsf;
-  if ( myBlock.GetLayersTransformation(trsf))
+  if ( myBlock.GetLayersTransformation( trsf, thePrism ))
   {
     // loop on nodes inside the bottom face
     TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
@@ -973,7 +1045,7 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
   SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
 
   TProjction1dAlgo* projector1D = TProjction1dAlgo::instance( this );
-  StdMeshers_Quadrangle_2D* quadAlgo = TQuadrangleAlgo::instance( this, mesh );
+  StdMeshers_Quadrangle_2D* quadAlgo = TQuadrangleAlgo::instance( this, myHelper );
 
   SMESH_HypoFilter hyp1dFilter( SMESH_HypoFilter::IsAlgo(),/*not=*/true);
   hyp1dFilter.And( SMESH_HypoFilter::HasDim( 1 ));
@@ -1002,6 +1074,15 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
       }
     }
     wgt2quad.insert( make_pair( wgt, iW ));
+
+    // in quadratic mesh, pass ignoreMediumNodes to quad sides
+    if ( myHelper->GetIsQuadratic() )
+    {
+      quad = thePrism.myWallQuads[iW].begin();
+      for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
+        for ( int i = 0; i < NB_QUAD_SIDES; ++i )
+          (*quad)->side[ i ]->SetIgnoreMediumNodes( true );
+    }
   }
 
   // Project 'vertical' EDGEs, from left to right
@@ -1174,20 +1255,28 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
       // -------------------------------
       const TopoDS_Face& face = (*quad)->face;
       SMESH_subMesh* fSM = mesh->GetSubMesh( face );
-      if ( fSM->IsMeshComputed() ) continue;
-
-      // make all EDGES meshed
-      fSM->ComputeSubMeshStateEngine( SMESH_subMesh::COMPUTE );
-      if ( !fSM->SubMeshesComputed() )
-        return toSM( error( COMPERR_BAD_INPUT_MESH,
-                            "Not all edges have valid algorithm and hypothesis"));
-      // mesh the <face>
-      quadAlgo->InitComputeError();
-      bool ok = quadAlgo->Compute( *mesh, face );
-      fSM->GetComputeError() = quadAlgo->GetComputeError();
-      if ( !ok )
-        return false;
-      fSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+      if ( ! fSM->IsMeshComputed() )
+      {
+        // make all EDGES meshed
+        fSM->ComputeSubMeshStateEngine( SMESH_subMesh::COMPUTE );
+        if ( !fSM->SubMeshesComputed() )
+          return toSM( error( COMPERR_BAD_INPUT_MESH,
+                              "Not all edges have valid algorithm and hypothesis"));
+        // mesh the <face>
+        quadAlgo->InitComputeError();
+        bool ok = quadAlgo->Compute( *mesh, face );
+        fSM->GetComputeError() = quadAlgo->GetComputeError();
+        if ( !ok )
+          return false;
+        fSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+      }
+      if ( myHelper->GetIsQuadratic() )
+      {
+        // fill myHelper with medium nodes built by quadAlgo
+        SMDS_ElemIteratorPtr fIt = fSM->GetSubMeshDS()->GetElements();
+        while ( fIt->more() )
+          myHelper->AddTLinks( dynamic_cast<const SMDS_MeshFace*>( fIt->next() ));
+      }
     }
   }
 
@@ -1452,7 +1541,12 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top()
   SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
 
   if ( !botSMDS || botSMDS->NbElements() == 0 )
-    return toSM( error(TCom("No elememts on face #") << botSM->GetId() ));
+  {
+    _gen->Compute( *myHelper->GetMesh(), botSM->GetSubShape() );
+    botSMDS = botSM->GetSubMeshDS();
+    if ( !botSMDS || botSMDS->NbElements() == 0 )
+      return toSM( error(TCom("No elememts on face #") << botSM->GetId() ));
+  }
 
   bool needProject = !topSM->IsMeshComputed();
   if ( !needProject && 
@@ -1587,7 +1681,7 @@ bool StdMeshers_Prism_3D::projectBottomToTop()
   // if the bottom faces is orienetd OK then top faces must be reversed
   bool reverseTop = true;
   if ( myHelper->NbAncestors( botFace, *myBlock.Mesh(), TopAbs_SOLID ) > 1 )
-    reverseTop = ! SMESH_Algo::IsReversedSubMesh( TopoDS::Face( botFace ), meshDS );
+    reverseTop = ! myHelper->IsReversedSubMesh( TopoDS::Face( botFace ));
   int iFrw, iRev, *iPtr = &( reverseTop ? iRev : iFrw );
 
   // loop on bottom mesh faces
@@ -1859,7 +1953,7 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
     // Issue 0020843 - one of side FACEs is quasi-quadrilateral (not 4 EDGEs).
     // Remove from notQuadGeomSubMesh faces meshed with regular grid
     int nbQuasiQuads = removeQuasiQuads( notQuadGeomSubMesh, myHelper,
-                                         TQuadrangleAlgo::instance(this,myHelper->GetMesh()) );
+                                         TQuadrangleAlgo::instance(this,myHelper) );
     nbNotQuad -= nbQuasiQuads;
     if ( nbNotQuad > 2 )
       return toSM( error(COMPERR_BAD_SHAPE,
@@ -2341,7 +2435,8 @@ const TNodeColumn* StdMeshers_PrismAsBlock::GetNodeColumn(const SMDS_MeshNode* n
 //           from bottom to top.
 //=======================================================================
 
-bool StdMeshers_PrismAsBlock::GetLayersTransformation(vector<gp_Trsf> & trsf) const
+bool StdMeshers_PrismAsBlock::GetLayersTransformation(vector<gp_Trsf> &           trsf,
+                                                      const Prism_3D::TPrismTopo& prism) const
 {
   const int zSize = VerticalSize();
   if ( zSize < 3 ) return true;
@@ -2351,13 +2446,9 @@ bool StdMeshers_PrismAsBlock::GetLayersTransformation(vector<gp_Trsf> & trsf) co
 
   vector< const TNodeColumn* > columns;
   {
-    const TopoDS_Shape& baseFace = Shape(ID_BOT_FACE);
-    list< TopoDS_Edge > orderedEdges;
-    list< int >         nbEdgesInWires;
-    GetOrderedEdges( TopoDS::Face( baseFace ), orderedEdges, nbEdgesInWires );
     bool isReverse;
-    list< TopoDS_Edge >::iterator edgeIt = orderedEdges.begin();
-    for ( int iE = 0; iE < nbEdgesInWires.front(); ++iE, ++edgeIt )
+    list< TopoDS_Edge >::const_iterator edgeIt = prism.myBottomEdges.begin();
+    for ( int iE = 0; iE < prism.myNbEdgesInWires.front(); ++iE, ++edgeIt )
     {
       if ( BRep_Tool::Degenerated( *edgeIt )) continue;
       const TParam2ColumnMap* u2colMap =