Salome HOME
bos #20282 EDF 22320 - general compute fails
authoreap <eap@opencascade.com>
Thu, 12 Nov 2020 20:06:06 +0000 (23:06 +0300)
committereap <eap@opencascade.com>
Thu, 12 Nov 2020 20:06:06 +0000 (23:06 +0300)
src/SMESH/SMESH_Gen.cxx
src/SMESH/SMESH_Gen.hxx
src/SMESH/SMESH_HypoFilter.cxx
src/SMESH/SMESH_subMesh.cxx
src/SMESH/SMESH_subMesh.hxx
src/SMESHGUI/SMESHGUI_MeshOrderOp.cxx
src/StdMeshers/StdMeshers_Prism_3D.cxx
src/StdMeshers/StdMeshers_Prism_3D.hxx

index f00d3a4d5f4f506d93d01b9ec8de9feec342d7a8..6635311805968590d0925c6ec593dc4f387f2483 100644 (file)
@@ -63,6 +63,43 @@ using namespace std;
   #define env_sep ':'
 #endif
 
+namespace
+{
+  // a structure used to nullify SMESH_Gen field of SMESH_Hypothesis,
+  // which is needed for SMESH_Hypothesis not deleted before ~SMESH_Gen()
+  struct _Hyp : public SMESH_Hypothesis
+  {
+    void NullifyGen()
+    {
+      _gen = 0;
+    }
+  };
+
+  //================================================================================
+  /*!
+   * \brief Fill a map of shapes with all sub-shape of a sub-mesh
+   */
+  //================================================================================
+
+  TopTools_IndexedMapOfShape * fillAllowed( SMESH_subMesh*               sm,
+                                            const bool                   toFill,
+                                            TopTools_IndexedMapOfShape * allowedSub )
+  {
+    if ( !toFill || !allowedSub )
+    {
+      return nullptr;
+    }
+    if ( allowedSub->IsEmpty() )
+    {
+      allowedSub->ReSize( sm->DependsOn().size() + 1 );
+      allowedSub->Add( sm->GetSubShape() );
+      for ( const auto & key_sm : sm->DependsOn() )
+        allowedSub->Add( key_sm.second->GetSubShape() );
+    }
+    return allowedSub;
+  }
+}
+
 //=============================================================================
 /*!
  *  Constructor
@@ -79,19 +116,6 @@ SMESH_Gen::SMESH_Gen()
   _compute_canceled = false;
 }
 
-namespace
-{
-  // a structure used to nullify SMESH_Gen field of SMESH_Hypothesis,
-  // which is needed for SMESH_Hypothesis not deleted before ~SMESH_Gen()
-  struct _Hyp : public SMESH_Hypothesis
-  {
-    void NullifyGen()
-    {
-      _gen = 0;
-    }
-  };
-}
-
 //=============================================================================
 /*!
  * Destructor
@@ -138,11 +162,12 @@ SMESH_Mesh* SMESH_Gen::CreateMesh(bool theIsEmbeddedMode)
  */
 //=============================================================================
 
-bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
-                        const TopoDS_Shape &  aShape,
-                        const int             aFlags /*= COMPACT_MESH*/,
-                        const ::MeshDimension aDim /*=::MeshDim_3D*/,
-                        TSetOfInt*            aShapesId /*=0*/)
+bool SMESH_Gen::Compute(SMESH_Mesh &                aMesh,
+                        const TopoDS_Shape &        aShape,
+                        const int                   aFlags /*= COMPACT_MESH*/,
+                        const ::MeshDimension       aDim /*=::MeshDim_3D*/,
+                        TSetOfInt*                  aShapesId /*=0*/,
+                        TopTools_IndexedMapOfShape* anAllowedSubShapes/*=0*/)
 {
   MEMOSTAT;
 
@@ -152,7 +177,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
 
   bool ret = true;
 
-  SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
+  SMESH_subMesh *sm, *shapeSM = aMesh.GetSubMesh(aShape);
 
   const bool includeSelf = true;
   const bool complexShapeFirst = true;
@@ -168,13 +193,17 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
   if ( !aMesh.HasShapeToMesh() )
     computeEvent = SMESH_subMesh::COMPUTE_NOGEOM; // if several algos and no geometry
 
+  TopTools_IndexedMapOfShape *allowedSubShapes = anAllowedSubShapes, allowedSub;
+  if ( aShapeOnly && !allowedSubShapes )
+    allowedSubShapes = &allowedSub;
+
   if ( anUpward ) // is called from the below code in this method
   {
     // ===============================================
     // Mesh all the sub-shapes starting from vertices
     // ===============================================
 
-    smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst);
+    smIt = shapeSM->getDependsOnIterator(includeSelf, !complexShapeFirst);
     while ( smIt->more() )
     {
       SMESH_subMesh* smToCompute = smIt->next();
@@ -198,9 +227,11 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
       {
         if (_compute_canceled)
           return false;
+        smToCompute->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
         setCurrentSubMesh( smToCompute );
         smToCompute->ComputeStateEngine( computeEvent );
-        setCurrentSubMesh( NULL );
+        setCurrentSubMesh( nullptr );
+        smToCompute->SetAllowedSubShapes( nullptr );
       }
 
       // we check all the sub-meshes here and detect if any of them failed to compute
@@ -233,7 +264,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
     TopoDS_Shape algoShape;
     int prevShapeDim = -1, aShapeDim;
 
-    smIt = sm->getDependsOnIterator(includeSelf, complexShapeFirst);
+    smIt = shapeSM->getDependsOnIterator(includeSelf, complexShapeFirst);
     while ( smIt->more() )
     {
       SMESH_subMesh* smToCompute = smIt->next();
@@ -285,9 +316,11 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
         {
           if (_compute_canceled)
             return false;
+          smToCompute->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
           setCurrentSubMesh( smToCompute );
           smToCompute->ComputeStateEngine( computeEvent );
-          setCurrentSubMesh( NULL );
+          setCurrentSubMesh( nullptr );
+          smToCompute->SetAllowedSubShapes( nullptr );
           if ( aShapesId )
             aShapesId->insert( smToCompute->GetId() );
         }
@@ -335,7 +368,6 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
 
           const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
           const int aShapeDim = GetShapeDim( aSubShape );
-          //if ( aSubShape.ShapeType() == TopAbs_VERTEX ) continue;
           if ( aShapeDim < 1 ) continue;
 
           // check for preview dimension limitations
@@ -350,11 +382,14 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
           if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( smToCompute, filter, true))
           {
             if ( ! subAlgo->NeedDiscreteBoundary() ) continue;
+            TopTools_IndexedMapOfShape* localAllowed = allowedSubShapes;
+            if ( localAllowed && localAllowed->IsEmpty() )
+              localAllowed = 0; // prevent fillAllowed() with  aSubShape
+
             SMESH_Hypothesis::Hypothesis_Status status;
             if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
               // mesh a lower smToCompute starting from vertices
-              Compute( aMesh, aSubShape, aFlags | SHAPE_ONLY_UPWARD, aDim, aShapesId );
-              // Compute( aMesh, aSubShape, aShapeOnly, /*anUpward=*/true, aDim, aShapesId );
+              Compute( aMesh, aSubShape, aFlags | SHAPE_ONLY_UPWARD, aDim, aShapesId, localAllowed );
           }
         }
       }
@@ -373,9 +408,11 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
 
           if (_compute_canceled)
             return false;
+          sm->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
           setCurrentSubMesh( sm );
           sm->ComputeStateEngine( computeEvent );
           setCurrentSubMesh( NULL );
+          sm->SetAllowedSubShapes( nullptr );
           if ( aShapesId )
             aShapesId->insert( sm->GetId() );
         }
@@ -385,7 +422,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
     // -----------------------------------------------
     // mesh the rest sub-shapes starting from vertices
     // -----------------------------------------------
-    ret = Compute( aMesh, aShape, aFlags | UPWARD, aDim, aShapesId );
+    ret = Compute( aMesh, aShape, aFlags | UPWARD, aDim, aShapesId, allowedSubShapes );
   }
 
   MEMOSTAT;
@@ -399,7 +436,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
     SMESH_MesherHelper aHelper( aMesh );
     if ( aHelper.IsQuadraticMesh() != SMESH_MesherHelper::LINEAR )
     {
-      aHelper.FixQuadraticElements( sm->GetComputeError() );
+      aHelper.FixQuadraticElements( shapeSM->GetComputeError() );
     }
   }
 
index c94693a0e8c3c1ce70a27b02686bfdfe5009dea1..e73fe61756d0780a4a066355ee8c2bd01be6c588 100644 (file)
@@ -42,6 +42,7 @@
 #include <string>
 
 #include <TopoDS_Shape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
 
 class SMESHDS_Document;
 class SMESH_Algo;
@@ -83,13 +84,15 @@ public:
    *  \param aFlags - ComputeFlags. By default compute the whole mesh and compact at the end.
    *  \param aDim - upper level dimension of the mesh computation (for preview)
    *  \param aShapesId - list of shapes with computed mesh entities (elements or nodes)
+   *  \param anAllowedSubShapes - shapes to mesh only. Mesh all if empty or nullptr
    *  \retval bool - true if none sub-mesh failed to compute
    */
-  bool Compute(::SMESH_Mesh &        aMesh,
-               const TopoDS_Shape &  aShape,
-               const int             aFlags = COMPACT_MESH,
-               const ::MeshDimension aDim=::MeshDim_3D,
-               TSetOfInt*            aShapesId=0);
+  bool Compute(::SMESH_Mesh &              aMesh,
+               const TopoDS_Shape &        aShape,
+               const int                   aFlags = COMPACT_MESH,
+               const ::MeshDimension       aDim=::MeshDim_3D,
+               TSetOfInt*                  aShapesId=0,
+               TopTools_IndexedMapOfShape* anAllowedSubShapes=0);
 
   void PrepareCompute(::SMESH_Mesh &        aMesh,
                       const TopoDS_Shape &  aShape);
index e1100ac8fc5cc9f7e75b338b4d651ca53aeb76ec..ecbd64bdc8f9f33367e0fe645eb17a32d863475b 100644 (file)
@@ -156,7 +156,7 @@ void SMESH_HypoFilter::IsMoreLocalThanPredicate::findPreferable()
 
 //=======================================================================
 //function : IsMoreLocalThanPredicate::IsOk
-//purpose  : 
+//purpose  : Check if aShape is more local than this->_shape
 //=======================================================================
 
 bool SMESH_HypoFilter::IsMoreLocalThanPredicate::IsOk(const SMESH_Hypothesis* aHyp,
@@ -169,16 +169,23 @@ bool SMESH_HypoFilter::IsMoreLocalThanPredicate::IsOk(const SMESH_Hypothesis* aH
   if ( SMESH_MesherHelper::IsSubShape( aShape, /*mainShape=*/_shape ))
     return true;
 
-  if ( aShape.ShapeType() == TopAbs_COMPOUND && 
+  if ( aShape.ShapeType() == TopAbs_COMPOUND &&
        !SMESH_MesherHelper::IsSubShape( _shape, /*mainShape=*/aShape)) // issue 0020963
   {
-    for ( int type = TopAbs_SOLID; type < TopAbs_SHAPE; ++type )
-      if ( aHyp->GetDim() == SMESH_Gen::GetShapeDim( TopAbs_ShapeEnum( type )))
-        for ( TopExp_Explorer exp( aShape, TopAbs_ShapeEnum( type )); exp.More(); exp.Next())
-          if ( SMESH_MesherHelper::IsSubShape( exp.Current(), /*mainShape=*/_shape ))
-            return true;
+    // [bos#22320] compound of FACEs is MORE local than compound of SOLIDs
+    TopAbs_ShapeEnum givenType = SMESH_MesherHelper::GetGroupType( _shape );
+    TopAbs_ShapeEnum   hypType = SMESH_MesherHelper::GetGroupType( aShape );
+    if ( SMESH_Gen::GetShapeDim( givenType ) > SMESH_Gen::GetShapeDim( hypType ))
+    {
+      for ( int type = TopAbs_SOLID; type < TopAbs_SHAPE; ++type )
+        if ( aHyp->GetDim() == SMESH_Gen::GetShapeDim( TopAbs_ShapeEnum( type )))
+          for ( TopExp_Explorer exp( aShape, TopAbs_ShapeEnum( type )); exp.More(); exp.Next())
+            if ( SMESH_MesherHelper::IsSubShape( exp.Current(), /*mainShape=*/_shape ))
+              return true;
+    }
   }
 
+  // take forced sub-mesh priority into account
   if ( _preferableShapes.Contains( aShape ))
     return true; // issue 21559, Mesh_6
 
@@ -187,7 +194,7 @@ bool SMESH_HypoFilter::IsMoreLocalThanPredicate::IsOk(const SMESH_Hypothesis* aH
 
 //=======================================================================
 //function : SMESH_HypoFilter
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 SMESH_HypoFilter::SMESH_HypoFilter()
index 63344a5094ddf4fac4b14eb44d4428a30d333f03..4f8a56e85dd514adf445166b51dcc141e6826082 100644 (file)
@@ -110,6 +110,7 @@ SMESH_subMesh::SMESH_subMesh(int                  Id,
   }
   _computeCost = 0; // how costly is to compute this sub-mesh
   _realComputeCost = 0;
+  _allowedSubShapes = nullptr;
 }
 
 //=============================================================================
@@ -1478,11 +1479,14 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event)
         if (_father->HasShapeToMesh() ) {
           bool subComputed = false, subFailed = false;
           if (!algo->OnlyUnaryInput()) {
-            if ( event == COMPUTE /*&&
-                 ( algo->NeedDiscreteBoundary() || algo->SupportSubmeshes() )*/)
-              shape = getCollection( gen, algo, subComputed, subFailed, algo->SubMeshesToCompute());
-            else
-              subComputed = SubMeshesComputed( & subFailed );
+            //  --- commented for bos#22320 to compute all sub-shapes at once if possible;
+            //  --- in case COMPUTE_SUBMESH, set of sub-shapes is limited
+            //  --- by calling SetAllowedSubShapes()
+            // if ( event == COMPUTE )
+            //   shape = getCollection( gen, algo, subComputed, subFailed, algo->SubMeshesToComput;
+            // else
+            //   subComputed = SubMeshesComputed( & subFailed );
+            shape = getCollection( gen, algo, subComputed, subFailed, algo->SubMeshesToCompute());
           }
           else {
             subComputed = SubMeshesComputed();
@@ -1610,8 +1614,9 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event)
             ((SMESHDS_Hypothesis*)hyps.front())->SaveTo( hypStr.Stream() );
             hypStr << " ";
           }
-          cout << _algo->GetName()
-               << " " << _father->GetSubMesh( subS.Current() )->GetId()
+          cout << _father->GetSubMesh( subS.Current() )->GetId()
+               << " " << ( ret ? "OK" : "FAIL" )
+               << " " << _algo->GetName()
                << " " << hypStr << endl;
         }
 #endif
@@ -1747,6 +1752,8 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event)
       break;
     case COMPUTE:               // nothing to do
       break;
+    case COMPUTE_SUBMESH:       // nothing to do
+      break;
     case COMPUTE_CANCELED:      // nothing to do
       break;
     case CLEAN:
@@ -2140,6 +2147,8 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
     const TopoDS_Shape&  S = subMesh->_subShape;
     if ( S.ShapeType() != this->_subShape.ShapeType() )
       continue;
+    if ( _allowedSubShapes && !_allowedSubShapes->IsEmpty() && !_allowedSubShapes->Contains( S ))
+      continue;
     if ( subMesh == this )
     {
       aBuilder.Add( aCompound, S );
index 03dd98e491b9448c9cf04a8396f070004b62890f..6b610ea1d9c8f11aa1024279f198c404fdfa8a97 100644 (file)
@@ -36,6 +36,7 @@
 #include "Utils_SALOME_Exception.hxx"
 
 #include <TopoDS_Shape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
 
 #include <list>
 #include <map>
@@ -256,6 +257,12 @@ public:
   bool IsMeshComputed() const;
   // check if _subMeshDS contains mesh elements unless _alwaysComputed==true
 
+  /*!
+   * \brief Set sub-shapes that are allowed to compute at once by a multidimensional algo
+   */
+  void SetAllowedSubShapes( const TopTools_IndexedMapOfShape* subShapes )
+  { _allowedSubShapes = subShapes; }
+
   /*!
    * \brief Allow algo->Compute() if a subshape of lower dim is meshed but
    *        none mesh entity is bound to it
@@ -344,6 +351,8 @@ protected:
   // mesh several edges as a whole and leave some of them  without mesh entities
   bool                  _alwaysComputed;
 
+  const TopTools_IndexedMapOfShape* _allowedSubShapes; // allowed to be returned by getCollection()
+
 };
 
 #endif
index 2c17777a576f5e7dd07120111468f853a288ab56..4f459d435d7624e7b45ea44dc7f02962dde9488b 100644 (file)
@@ -53,7 +53,7 @@ SMESHGUI_MeshOrderOp::SMESHGUI_MeshOrderOp()
 {
   myDlg = new SMESHGUI_MeshOrderDlg( desktop() );
   
-  myHelpFileName = "constructing_meshes.html#mesh-order-anchor";
+  myHelpFileName = "constructing_meshes.html#submesh-order-anchor";
 }
 
 //================================================================================
index e6db9e5014f8fe75ce40c6642fbbe689733d409b..b35e76ae357ce433a4196246835d0aa49dbcf82b 100644 (file)
@@ -151,9 +151,10 @@ namespace
     // Clear collected data
     void reset()
     {
-      myFace2QuadMap.Clear();
       StdMeshers_Quadrangle_2D::myQuadList.clear();
       StdMeshers_Quadrangle_2D::myHelper = nullptr;
+      StdMeshers_Quadrangle_2D::myProxyMesh.reset();
+      myFace2QuadMap.Clear();
     }
 
     //================================================================================
@@ -778,7 +779,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
   SMESH_MesherHelper helper( theMesh );
   myHelper = &helper;
   myPrevBottomSM = 0;
-  TQuadrangleAlgo::Cleaner( TQuadrangleAlgo::instance( this ));
+  TQuadrangleAlgo::Cleaner quadCleaner( TQuadrangleAlgo::instance( this ));
 
   int nbSolids = helper.Count( theShape, TopAbs_SOLID, /*skipSame=*/false );
   if ( nbSolids < 1 )
@@ -848,6 +849,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
   }
 
   TopTools_MapOfShape meshedSolids;
+  NCollection_DataMap< TopoDS_Shape, SMESH_subMesh* > meshedFace2AlgoSM;
   list< Prism_3D::TPrismTopo > meshedPrism;
   list< TopoDS_Face > suspectSourceFaces;
   TopTools_ListIteratorOfListOfShape solidIt;
@@ -871,6 +873,8 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
         {
           prism.Clear();
           prism.myBottom = face;
+          if ( meshedFace2AlgoSM.IsBound( face ))
+            prism.myAlgoSM = meshedFace2AlgoSM.Find( face );
           if ( !initPrism( prism, solid, selectBottom ) ||
                !compute( prism ))
             return false;
@@ -880,6 +884,11 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
                !myHelper->IsStructured( theMesh.GetSubMesh( prism.myTop )))
           {
             meshedFaces.push_front( prism.myTop );
+            if ( prism.myAlgoSM  && prism.myAlgoSM->GetAlgo() )
+            {
+              meshedFace2AlgoSM.Bind( prism.myTop,    prism.myAlgoSM );
+              meshedFace2AlgoSM.Bind( prism.myBottom, prism.myAlgoSM );
+            }
           }
           else
           {
@@ -914,9 +923,18 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
               solidList.Remove( solidIt );
               continue; // already computed prism
             }
-            if ( myHelper->IsBlock( solid )) {
-              solidIt.Next();
-              continue; // too trivial
+            if ( myHelper->IsBlock( solid ))
+            {
+              bool isStructBase = true;
+              if ( prismIt->myAlgoSM )
+                isStructBase = ( myHelper->IsSameElemGeometry( prismIt->myAlgoSM->GetSubMeshDS(),
+                                                               SMDSGeom_QUADRANGLE ) &&
+                                 myHelper->IsStructured(prismIt->myAlgoSM ));
+              if ( isStructBase )
+              {
+                solidIt.Next();
+                continue; // too trivial
+              }
             }
             // 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 ].grid->Edge(0);
@@ -935,27 +953,41 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
                 }
               prism.Clear();
               prism.myBottom = candidateF;
+              prism.myAlgoSM = prismIt->myAlgoSM;
               mySetErrorToSM = false;
               if ( !myHelper->IsSubShape( candidateF, prismIt->myShape3D ) &&
                    myHelper ->IsSubShape( candidateF, solid ) &&
                    !myHelper->GetMesh()->GetSubMesh( candidateF )->IsMeshComputed() &&
                    initPrism( prism, solid, /*selectBottom=*/false ) &&
                    !myHelper->GetMesh()->GetSubMesh( prism.myTop )->IsMeshComputed() &&
-                   !myHelper->GetMesh()->GetSubMesh( prism.myBottom )->IsMeshComputed() &&
-                   project2dMesh( sourceF, prism.myBottom ))
+                   !myHelper->GetMesh()->GetSubMesh( prism.myBottom )->IsMeshComputed() )
               {
-                mySetErrorToSM = true;
-                if ( !compute( prism ))
-                  return false;
-                SMESHDS_SubMesh* smDS = theMesh.GetMeshDS()->MeshElements( prism.myTop );
-                if ( !myHelper->IsSameElemGeometry( smDS, SMDSGeom_QUADRANGLE ))
+                if ( project2dMesh( sourceF, prism.myBottom ))
+                {
+                  mySetErrorToSM = true;
+                  if ( !compute( prism ))
+                    return false;
+                  SMESHDS_SubMesh* smDS = theMesh.GetMeshDS()->MeshElements( prism.myTop );
+                  if ( !myHelper->IsSameElemGeometry( smDS, SMDSGeom_QUADRANGLE ))
+                  {
+                    meshedFaces.push_front( prism.myTop );
+                    meshedFaces.push_front( prism.myBottom );
+                    selectBottom = false;
+                    if ( prism.myAlgoSM  && prism.myAlgoSM->GetAlgo() )
+                    {
+                      meshedFace2AlgoSM.Bind( prism.myTop, prism.myAlgoSM );
+                      meshedFace2AlgoSM.Bind( prism.myBottom, prism.myAlgoSM );
+                    }
+                  }
+                  meshedPrism.push_back( prism );
+                  meshedSolids.Add( solid );
+                }
+                else
                 {
-                  meshedFaces.push_front( prism.myTop );
-                  meshedFaces.push_front( prism.myBottom );
-                  selectBottom = false;
+                  meshedFaces.push_back( prism.myBottom );
+                  if ( prism.myAlgoSM && prism.myAlgoSM->GetAlgo() )
+                    meshedFace2AlgoSM.Bind( prism.myBottom, prism.myAlgoSM );
                 }
-                meshedPrism.push_back( prism );
-                meshedSolids.Add( solid );
               }
               InitComputeError();
             }
@@ -1008,7 +1040,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
             allSubMeComputed = smIt->next()->IsMeshComputed();
           if ( allSubMeComputed )
           {
-            faceSM->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+            faceSM->ComputeStateEngine( SMESH_subMesh::COMPUTE_SUBMESH );
             if ( !faceSM->IsEmpty() ) {
               meshedFaces.push_front( face ); // higher priority
               selectBottom = true;
@@ -1562,8 +1594,9 @@ bool StdMeshers_Prism_3D::computeBase(const Prism_3D::TPrismTopo& thePrism)
   {
     // find any applicable algorithm assigned to any FACE of the main shape
     std::vector< TopoDS_Shape > faces;
-    if ( myPrevBottomSM &&
-         myPrevBottomSM->GetAlgo()->IsApplicableToShape( thePrism.myBottom, /*all=*/false ))
+    if ( thePrism.myAlgoSM && thePrism.myAlgoSM->GetAlgo() )
+      faces.push_back( thePrism.myAlgoSM->GetSubShape() );
+    if ( myPrevBottomSM && myPrevBottomSM->GetAlgo() )
       faces.push_back( myPrevBottomSM->GetSubShape() );
 
     TopExp_Explorer faceIt( mesh->GetShapeToMesh(), TopAbs_FACE );
@@ -1588,7 +1621,7 @@ bool StdMeshers_Prism_3D::computeBase(const Prism_3D::TPrismTopo& thePrism)
           while ( smIt->more() && subOK )
           {
             SMESH_subMesh* sub = smIt->next();
-            sub->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+            sub->ComputeStateEngine( SMESH_subMesh::COMPUTE_SUBMESH );
             subOK = sub->IsMeshComputed();
           }
           if ( !subOK )
@@ -1596,23 +1629,31 @@ bool StdMeshers_Prism_3D::computeBase(const Prism_3D::TPrismTopo& thePrism)
         }
         try {
           OCC_CATCH_SIGNALS;
+
+          Hypothesis_Status status;
+          algo->CheckHypothesis( *mesh, faces[i], status );
           algo->InitComputeError();
-          algo->Compute( *mesh, botSM->GetSubShape() );
+          if ( algo->Compute( *mesh, botSM->GetSubShape() ))
+          {
+            myPrevBottomSM = thePrism.myAlgoSM = mesh->GetSubMesh( faces[i] );
+            break;
+          }
         }
         catch (...) {
         }
       }
     }
   }
+  else
+  {
+    myPrevBottomSM = thePrism.myAlgoSM = botSM;
+  }
 
   if ( botSM->IsEmpty() )
     return error( COMPERR_BAD_INPUT_MESH,
                   TCom( "No mesher defined to compute the base face #")
                   << shapeID( thePrism.myBottom ));
 
-  if ( botSM->GetAlgo() )
-    myPrevBottomSM = botSM;
-
   return true;
 }
 
@@ -3504,6 +3545,7 @@ namespace Prism_3D
     myBottomEdges.clear();
     myNbEdgesInWires.clear();
     myWallQuads.clear();
+    myAlgoSM = nullptr;
   }
 
   //================================================================================
@@ -4806,7 +4848,7 @@ TopoDS_Edge StdMeshers_PrismAsBlock::TSideFace::GetEdge(const int iEdge) const
       column = & ( myParamToColumnMap->rbegin()->second );
     else
       column = & ( myParamToColumnMap->begin()->second );
-    if ( column->size() > 0 )
+    if ( column->size() > 1 )
       edge = myHelper.GetSubShapeByNode( (*column)[ 1 ], meshDS );
     if ( edge.IsNull() || edge.ShapeType() == TopAbs_VERTEX )
       node = column->front();
index d910bdd27343e228d397c3f92ca9c2e52efec89d..850e01ee0b21c162648bd532d54947c300d40bf5 100644 (file)
@@ -106,6 +106,7 @@ namespace Prism_3D
     std::list< int >         myNbEdgesInWires;
 
     bool                     myNotQuadOnTop;
+    mutable SMESH_subMesh*   myAlgoSM; // sub-mesh with algo which computed myBottom
 
     size_t NbWires() const { return myNbEdgesInWires.size(); }