+ {
+ // reload sub-meshes from shDim2sm into smWithAlgoSupportingSubmeshes
+ // so that more local algos to go first
+ if ( prevShapeDim != aShapeDim )
+ {
+ prevShapeDim = aShapeDim;
+ for ( shDim2smIt = shDim2sm.rbegin(); shDim2smIt != shDim2sm.rend(); ++shDim2smIt )
+ if ( shDim2smIt->first == globalAlgoDim )
+ smWithAlgoSupportingSubmeshes[ aShapeDim ].push_back( shDim2smIt->second );
+ else
+ smWithAlgoSupportingSubmeshes[ aShapeDim ].push_front( shDim2smIt->second );
+ shDim2sm.clear();
+ }
+ // add smToCompute to shDim2sm map
+ if ( algoShape.IsSame( aMesh.GetShapeToMesh() ))
+ {
+ aShapeDim = globalAlgoDim; // to compute last
+ }
+ else
+ {
+ aShapeDim = GetShapeDim( algoShape );
+ if ( algoShape.ShapeType() == TopAbs_COMPOUND )
+ {
+ TopoDS_Iterator it( algoShape );
+ aShapeDim += GetShapeDim( it.Value() );
+ }
+ }
+ shDim2sm.insert( make_pair( aShapeDim, smToCompute ));
+ }
+ else // Compute w/o support of sub-meshes
+ {
+ if (_compute_canceled)
+ return false;
+ setCurrentSubMesh( smToCompute );
+ smToCompute->ComputeStateEngine( computeEvent );
+ setCurrentSubMesh( NULL );
+ if ( aShapesId )
+ aShapesId->insert( smToCompute->GetId() );
+ }
+ }
+ }
+ // reload sub-meshes from shDim2sm into smWithAlgoSupportingSubmeshes
+ for ( shDim2smIt = shDim2sm.rbegin(); shDim2smIt != shDim2sm.rend(); ++shDim2smIt )
+ if ( shDim2smIt->first == globalAlgoDim )
+ smWithAlgoSupportingSubmeshes[3].push_back( shDim2smIt->second );
+ else
+ smWithAlgoSupportingSubmeshes[0].push_front( shDim2smIt->second );
+
+ // ======================================================
+ // Apply all-dimensional algorithms supporing sub-meshes
+ // ======================================================
+
+ std::vector< SMESH_subMesh* > smVec;
+ for ( aShapeDim = 0; aShapeDim < 4; ++aShapeDim )
+ {
+ // ------------------------------------------------
+ // sort list of sub-meshes according to mesh order
+ // ------------------------------------------------
+ smVec.assign( smWithAlgoSupportingSubmeshes[ aShapeDim ].begin(),
+ smWithAlgoSupportingSubmeshes[ aShapeDim ].end() );
+ aMesh.SortByMeshOrder( smVec );
+
+ // ------------------------------------------------------------
+ // compute sub-meshes with local uni-dimensional algos under
+ // sub-meshes with all-dimensional algos
+ // ------------------------------------------------------------
+ // start from lower shapes
+ for ( size_t i = 0; i < smVec.size(); ++i )
+ {
+ sm = smVec[i];
+
+ // get a shape the algo is assigned to
+ if ( !GetAlgo( sm, & algoShape ))
+ continue; // strange...
+
+ // look for more local algos
+ smIt = sm->getDependsOnIterator(!includeSelf, !complexShapeFirst);
+ while ( smIt->more() )
+ {
+ SMESH_subMesh* smToCompute = smIt->next();
+
+ 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
+ if ( aShapesId && GetShapeDim( aSubShape.ShapeType() ) > (int)aDim )
+ continue;
+
+ SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
+ filter
+ .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
+ .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));
+
+ if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( smToCompute, filter, true))
+ {
+ if ( ! subAlgo->NeedDiscreteBoundary() ) continue;
+ 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 );
+ }
+ }
+ }
+ // --------------------------------
+ // apply the all-dimensional algos
+ // --------------------------------
+ for ( size_t i = 0; i < smVec.size(); ++i )
+ {
+ sm = smVec[i];
+ if ( sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
+ {
+ const TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType();
+ // check for preview dimension limitations
+ if ( aShapesId && GetShapeDim( shapeType ) > (int)aDim )
+ continue;
+
+ if (_compute_canceled)
+ return false;
+ setCurrentSubMesh( sm );
+ sm->ComputeStateEngine( computeEvent );
+ setCurrentSubMesh( NULL );
+ if ( aShapesId )
+ aShapesId->insert( sm->GetId() );
+ }
+ }
+ } // loop on shape dimensions
+
+ // -----------------------------------------------
+ // mesh the rest sub-shapes starting from vertices
+ // -----------------------------------------------
+ ret = Compute( aMesh, aShape, aFlags | UPWARD, aDim, aShapesId );
+ }
+
+ MEMOSTAT;
+
+ // fix quadratic mesh by bending iternal links near concave boundary
+ if ( aCompactMesh && // a final compute
+ aShape.IsSame( aMesh.GetShapeToMesh() ) &&
+ !aShapesId && // not preview
+ ret ) // everything is OK
+ {
+ SMESH_MesherHelper aHelper( aMesh );
+ if ( aHelper.IsQuadraticMesh() != SMESH_MesherHelper::LINEAR )
+ {
+ aHelper.FixQuadraticElements( sm->GetComputeError() );
+ }
+ }
+
+ if ( aCompactMesh )
+ aMesh.GetMeshDS()->compactMesh();
+
+ return ret;
+}
+
+//=============================================================================
+/*!
+ * Prepare Compute a mesh
+ */
+//=============================================================================
+void SMESH_Gen::PrepareCompute(SMESH_Mesh & aMesh,
+ const TopoDS_Shape & aShape)
+{
+ _compute_canceled = false;
+ resetCurrentSubMesh();
+}
+
+//=============================================================================
+/*!
+ * Cancel Compute a mesh
+ */
+//=============================================================================
+void SMESH_Gen::CancelCompute(SMESH_Mesh & aMesh,
+ const TopoDS_Shape & aShape)
+{
+ _compute_canceled = true;
+ if ( const SMESH_subMesh* sm = GetCurrentSubMesh() )
+ {
+ const_cast< SMESH_subMesh* >( sm )->ComputeStateEngine( SMESH_subMesh::COMPUTE_CANCELED );
+ }
+ resetCurrentSubMesh();
+}
+
+//================================================================================
+/*!
+ * \brief Returns a sub-mesh being currently computed
+ */
+//================================================================================
+
+const SMESH_subMesh* SMESH_Gen::GetCurrentSubMesh() const
+{
+ return _sm_current.empty() ? 0 : _sm_current.back();
+}
+
+//================================================================================
+/*!
+ * \brief Sets a sub-mesh being currently computed.
+ *
+ * An algorithm can call Compute() for a sub-shape, hence we keep a stack of sub-meshes
+ */
+//================================================================================
+
+void SMESH_Gen::setCurrentSubMesh(SMESH_subMesh* sm)
+{
+ if ( sm )
+ _sm_current.push_back( sm );
+
+ else if ( !_sm_current.empty() )
+ _sm_current.pop_back();
+}
+
+void SMESH_Gen::resetCurrentSubMesh()
+{
+ _sm_current.clear();
+}
+
+//=============================================================================
+/*!
+ * Evaluate a mesh
+ */
+//=============================================================================
+
+bool SMESH_Gen::Evaluate(SMESH_Mesh & aMesh,
+ const TopoDS_Shape & aShape,
+ MapShapeNbElems& aResMap,
+ const bool anUpward,
+ TSetOfInt* aShapesId)
+{
+ bool ret = true;
+
+ SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
+
+ const bool includeSelf = true;
+ const bool complexShapeFirst = true;
+ SMESH_subMeshIteratorPtr smIt;
+
+ if ( anUpward ) { // is called from below code here
+ // -----------------------------------------------
+ // mesh all the sub-shapes starting from vertices
+ // -----------------------------------------------
+ smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst);
+ while ( smIt->more() ) {
+ SMESH_subMesh* smToCompute = smIt->next();
+
+ // do not mesh vertices of a pseudo shape
+ const TopAbs_ShapeEnum shapeType = smToCompute->GetSubShape().ShapeType();
+ //if ( !aMesh.HasShapeToMesh() && shapeType == TopAbs_VERTEX )
+ // continue;
+ if ( !aMesh.HasShapeToMesh() ) {
+ if( shapeType == TopAbs_VERTEX || shapeType == TopAbs_WIRE ||
+ shapeType == TopAbs_SHELL )
+ continue;