+ // check for preview dimension limitations
+ if ( aShapesId && GetShapeDim( aShType ) > (int)aDim )
+ {
+ // clear compute state not to show previous compute errors
+ // if preview invoked less dimension less than previous
+ smToCompute->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+ continue;
+ }
+
+ if (smToCompute->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
+ {
+ if (_compute_canceled)
+ return false;
+ _sm_current = smToCompute;
+ smToCompute->ComputeStateEngine( computeEvent );
+ _sm_current = NULL;
+ }
+
+ // we check all the submeshes here and detect if any of them failed to compute
+ if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE)
+ ret = false;
+ else if ( aShapesId )
+ aShapesId->insert( smToCompute->GetId() );
+ }
+ //aMesh.GetMeshDS()->Modified();
+ return ret;
+ }
+ else
+ {
+ // -----------------------------------------------------------------
+ // apply algos that DO NOT require Discreteized boundaries and DO NOT
+ // support submeshes, starting from the most complex shapes
+ // and collect submeshes with algos that DO support submeshes
+ // -----------------------------------------------------------------
+ list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes;
+
+ // map to sort sm with same dim algos according to dim of
+ // the shape the algo assigned to (issue 0021217)
+ multimap< int, SMESH_subMesh* > shDim2sm;
+ multimap< int, SMESH_subMesh* >::reverse_iterator shDim2smIt;
+ TopoDS_Shape algoShape;
+ int prevShapeDim = -1;
+
+ smIt = sm->getDependsOnIterator(includeSelf, complexShapeFirst);
+ while ( smIt->more() )
+ {
+ SMESH_subMesh* smToCompute = smIt->next();
+ if ( smToCompute->GetComputeState() != SMESH_subMesh::READY_TO_COMPUTE )
+ continue;
+
+ const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
+ int aShapeDim = GetShapeDim( aSubShape );
+ if ( aShapeDim < 1 ) break;
+
+ // check for preview dimension limitations
+ if ( aShapesId && aShapeDim > (int)aDim )
+ continue;
+
+ SMESH_Algo* algo = GetAlgo( aMesh, aSubShape, &algoShape );
+ if ( algo && !algo->NeedDiscreteBoundary() )
+ {
+ if ( algo->SupportSubmeshes() )
+ {
+ // 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.push_back( shDim2smIt->second );
+ else
+ smWithAlgoSupportingSubmeshes.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
+ {
+ if (_compute_canceled)
+ return false;
+ _sm_current = smToCompute;
+ smToCompute->ComputeStateEngine( computeEvent );
+ _sm_current = 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.push_back( shDim2smIt->second );
+ else
+ smWithAlgoSupportingSubmeshes.push_front( shDim2smIt->second );
+
+ // ------------------------------------------------------------
+ // sort list of submeshes according to mesh order
+ // ------------------------------------------------------------
+ aMesh.SortByMeshOrder( smWithAlgoSupportingSubmeshes );
+
+ // ------------------------------------------------------------
+ // compute submeshes under shapes with algos that DO NOT require
+ // Discreteized boundaries and DO support submeshes
+ // ------------------------------------------------------------
+ list< SMESH_subMesh* >::iterator subIt, subEnd;
+ subIt = smWithAlgoSupportingSubmeshes.begin();
+ subEnd = smWithAlgoSupportingSubmeshes.end();
+ // start from lower shapes
+ for ( ; subIt != subEnd; ++subIt )
+ {
+ sm = *subIt;
+
+ // get a shape the algo is assigned to
+ if ( !GetAlgo( aMesh, sm->GetSubShape(), & 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( aSubShape, 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, /*anUpward=*/true, aDim, aShapesId );
+ }
+ }
+ }
+ // ----------------------------------------------------------
+ // apply the algos that do not require Discreteized boundaries
+ // ----------------------------------------------------------
+ for ( subIt = smWithAlgoSupportingSubmeshes.begin(); subIt != subEnd; ++subIt )
+ {
+ sm = *subIt;
+ if ( sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
+ {
+ const TopAbs_ShapeEnum aShType = sm->GetSubShape().ShapeType();
+ // check for preview dimension limitations
+ if ( aShapesId && GetShapeDim( aShType ) > (int)aDim )
+ continue;
+
+ if (_compute_canceled)
+ return false;
+ _sm_current = sm;
+ sm->ComputeStateEngine( computeEvent );
+ _sm_current = NULL;
+ if ( aShapesId )
+ aShapesId->insert( sm->GetId() );
+ }
+ }
+ // -----------------------------------------------
+ // mesh the rest sub-shapes starting from vertices
+ // -----------------------------------------------
+ ret = Compute( aMesh, aShape, /*anUpward=*/true, aDim, aShapesId );
+ }
+
+ MESSAGE( "VSR - SMESH_Gen::Compute() finished, OK = " << ret);
+ MEMOSTAT;
+
+ SMESHDS_Mesh *myMesh = aMesh.GetMeshDS();
+ MESSAGE("*** compactMesh after compute");
+ myMesh->compactMesh();
+
+ // fix quadratic mesh by bending iternal links near concave boundary
+ if ( 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() );
+ }
+ }
+ return ret;
+}
+
+
+#ifdef WITH_SMESH_CANCEL_COMPUTE
+//=============================================================================
+/*!
+ * Prepare Compute a mesh
+ */
+//=============================================================================
+void SMESH_Gen::PrepareCompute(SMESH_Mesh & aMesh,
+ const TopoDS_Shape & aShape)
+{
+ _compute_canceled = false;
+ _sm_current = NULL;
+}
+//=============================================================================
+/*!
+ * Cancel Compute a mesh
+ */
+//=============================================================================
+void SMESH_Gen::CancelCompute(SMESH_Mesh & aMesh,
+ const TopoDS_Shape & aShape)
+{
+ _compute_canceled = true;
+ if(_sm_current)
+ {
+ _sm_current->ComputeStateEngine( SMESH_subMesh::COMPUTE_CANCELED );
+ }