+ switch ( event ) {
+ case MODIF_ALGO_STATE:
+ case COMPUTE:
+ case COMPUTE_SUBMESH:
+ //case COMPUTE_CANCELED:
+ case CLEAN:
+ //case SUBMESH_COMPUTED:
+ //case SUBMESH_RESTORED:
+ //case SUBMESH_LOADED:
+ //case MESH_ENTITY_REMOVED:
+ //case CHECK_COMPUTE_STATE:
+ _computeError.reset(); break;
+ default:;
+ }
+
+ if ( event == CLEAN )
+ _alwaysComputed = false; // Unset 'true' set by MergeNodes() (issue 0022182)
+
+ if (_subShape.ShapeType() == TopAbs_VERTEX)
+ {
+ _computeState = READY_TO_COMPUTE;
+ SMESHDS_SubMesh* smDS = GetSubMeshDS();
+ if ( smDS && smDS->NbNodes() )
+ {
+ if ( event == CLEAN ) {
+ cleanDependants();
+ cleanSubMesh( this );
+ }
+ else
+ _computeState = COMPUTE_OK;
+ }
+ else if (( event == COMPUTE || event == COMPUTE_SUBMESH )
+ && !_alwaysComputed )
+ {
+ const TopoDS_Vertex & V = TopoDS::Vertex( _subShape );
+ gp_Pnt P = BRep_Tool::Pnt(V);
+ if ( SMDS_MeshNode * n = _father->GetMeshDS()->AddNode(P.X(), P.Y(), P.Z()) ) {
+ _father->GetMeshDS()->SetNodeOnVertex(n,_Id);
+ _computeState = COMPUTE_OK;
+ }
+ }
+ if ( event == MODIF_ALGO_STATE )
+ cleanDependants();
+ return true;
+ }
+ SMESH_Gen *gen = _father->GetGen();
+ SMESH_Algo *algo = 0;
+ bool ret = true;
+ SMESH_Hypothesis::Hypothesis_Status hyp_status;
+ //algo_state oldAlgoState = (algo_state) GetAlgoState();
+
+ switch (_computeState)
+ {
+
+ // ----------------------------------------------------------------------
+
+ case NOT_READY:
+ switch (event)
+ {
+ case MODIF_ALGO_STATE:
+ algo = GetAlgo();
+ if (algo && !algo->NeedDiscreteBoundary())
+ cleanDependsOn( algo ); // clean sub-meshes with event CLEAN
+ if ( _algoState == HYP_OK )
+ _computeState = READY_TO_COMPUTE;
+ break;
+ case COMPUTE: // nothing to do
+ case COMPUTE_SUBMESH:
+ break;
+ case COMPUTE_CANCELED: // nothing to do
+ break;
+ case CLEAN:
+ cleanDependants();
+ removeSubMeshElementsAndNodes();
+ break;
+ case SUBMESH_COMPUTED: // nothing to do
+ break;
+ case SUBMESH_RESTORED:
+ ComputeSubMeshStateEngine( SUBMESH_RESTORED );
+ break;
+ case MESH_ENTITY_REMOVED:
+ break;
+ case SUBMESH_LOADED:
+ loadDependentMeshes();
+ ComputeSubMeshStateEngine( SUBMESH_LOADED );
+ //break;
+ case CHECK_COMPUTE_STATE:
+ if ( IsMeshComputed() )
+ _computeState = COMPUTE_OK;
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ break;
+
+ // ----------------------------------------------------------------------
+
+ case READY_TO_COMPUTE:
+ switch (event)
+ {
+ case MODIF_ALGO_STATE:
+ _computeState = NOT_READY;
+ algo = GetAlgo();
+ if (algo)
+ {
+ if (!algo->NeedDiscreteBoundary())
+ cleanDependsOn( algo ); // clean sub-meshes with event CLEAN
+ if ( _algoState == HYP_OK )
+ _computeState = READY_TO_COMPUTE;
+ }
+ break;
+
+ case COMPUTE_NOGEOM: // no geometry; can be several algos
+ if ( !_father->HasShapeToMesh() )
+ {
+ algo = GetAlgo(); // current algo
+ if ( algo )
+ {
+ // apply algos in the order of increasing dimension
+ std::list< const SMESHDS_Hypothesis * > algos = _father->GetHypothesisList( _subShape );
+ for ( int t = SMESHDS_Hypothesis::ALGO_1D; t <= SMESHDS_Hypothesis::ALGO_3D; ++t )
+ {
+ std::list<const SMESHDS_Hypothesis *>::iterator al = algos.begin();
+ for ( ; al != algos.end(); ++al )
+ if ( (*al)->GetType() == t )
+ {
+ _algo = (SMESH_Algo*) *al;
+ _computeState = READY_TO_COMPUTE;
+ if ( !ComputeStateEngine( COMPUTE ))
+ break;
+ }
+ }
+ _algo = algo; // restore
+ }
+ break;
+ }
+ case COMPUTE:
+ case COMPUTE_SUBMESH:
+ {
+ algo = GetAlgo();
+ ASSERT(algo);
+ ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
+ if (!ret)
+ {
+ MESSAGE("***** verify compute state *****");
+ _computeState = NOT_READY;
+ setAlgoState(MISSING_HYP);
+ break;
+ }
+ TopoDS_Shape shape = _subShape;
+ algo->SubMeshesToCompute().assign( 1, this );
+ // check submeshes needed
+ 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 );
+ }
+ else {
+ subComputed = SubMeshesComputed();
+ }
+ ret = ( algo->NeedDiscreteBoundary() ? subComputed :
+ algo->SupportSubmeshes() ? !subFailed :
+ ( !subComputed || _father->IsNotConformAllowed() ));
+ if (!ret)
+ {
+ _computeState = FAILED_TO_COMPUTE;
+ if ( !algo->NeedDiscreteBoundary() && !subFailed )
+ _computeError =
+ SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH,
+ "Unexpected computed sub-mesh",algo);
+ break; // goto exit
+ }
+ }
+ // Compute
+
+ // to restore cout that may be redirected by algo
+ std::streambuf* coutBuffer = std::cout.rdbuf();
+
+ //cleanDependants(); for "UseExisting_*D" algos
+ //removeSubMeshElementsAndNodes();
+ loadDependentMeshes();
+ ret = false;
+ _computeState = FAILED_TO_COMPUTE;
+ _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
+ try {
+ OCC_CATCH_SIGNALS;
+
+ algo->InitComputeError();
+
+ MemoryReserve aMemoryReserve;
+ SMDS_Mesh::CheckMemory();
+ Kernel_Utils::Localizer loc;
+ if ( !_father->HasShapeToMesh() ) // no shape
+ {
+ SMESH_MesherHelper helper( *_father );
+ helper.SetSubShape( shape );
+ helper.SetElementsOnShape( true );
+ ret = algo->Compute(*_father, &helper );
+ }
+ else
+ {
+ ret = algo->Compute((*_father), shape);
+ }
+ // algo can set _computeError of submesh
+ _computeError = SMESH_ComputeError::Worst( _computeError, algo->GetComputeError() );
+ }
+ catch ( ::SMESH_ComputeError& comperr ) {
+ cout << " SMESH_ComputeError caught" << endl;
+ if ( !_computeError ) _computeError = SMESH_ComputeError::New();
+ *_computeError = comperr;
+ }
+ catch ( std::bad_alloc& exc ) {
+ MESSAGE("std::bad_alloc thrown inside algo->Compute()");
+ if ( _computeError ) {
+ _computeError->myName = COMPERR_MEMORY_PB;
+ }
+ cleanSubMesh( this );
+ throw exc;
+ }
+ catch ( Standard_OutOfMemory& exc ) {
+ MESSAGE("Standard_OutOfMemory thrown inside algo->Compute()");
+ if ( _computeError ) {
+ _computeError->myName = COMPERR_MEMORY_PB;
+ }
+ cleanSubMesh( this );
+ throw std::bad_alloc();
+ }
+ catch (Standard_Failure& ex) {
+ if ( !_computeError ) _computeError = SMESH_ComputeError::New();
+ _computeError->myName = COMPERR_OCC_EXCEPTION;
+ _computeError->myComment += ex.DynamicType()->Name();
+ if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) {
+ _computeError->myComment += ": ";
+ _computeError->myComment += ex.GetMessageString();
+ }
+ }
+ catch ( SALOME_Exception& S_ex ) {
+ const int skipSalomeShift = 7; /* to skip "Salome " of
+ "Salome Exception" prefix returned
+ by SALOME_Exception::what() */
+ if ( !_computeError ) _computeError = SMESH_ComputeError::New();
+ _computeError->myName = COMPERR_SLM_EXCEPTION;
+ _computeError->myComment = S_ex.what() + skipSalomeShift;
+ }
+ catch ( std::exception& exc ) {
+ if ( !_computeError ) _computeError = SMESH_ComputeError::New();
+ _computeError->myName = COMPERR_STD_EXCEPTION;
+ _computeError->myComment = exc.what();
+ }
+ catch ( ... ) {
+ if ( _computeError )
+ _computeError->myName = COMPERR_EXCEPTION;
+ else
+ ret = false;
+ }
+ std::cout.rdbuf( coutBuffer ); // restore cout that could be redirected by algo
+
+ // check if an error reported on any sub-shape
+ bool isComputeErrorSet = !checkComputeError( algo, ret, shape );
+ if ( isComputeErrorSet )
+ ret = false;
+ // check if anything was built
+ TopExp_Explorer subS(shape, _subShape.ShapeType());
+ if ( ret )
+ {
+ for (; ret && subS.More(); subS.Next())
+ if ( !_father->GetSubMesh( subS.Current() )->IsMeshComputed() &&
+ ( _subShape.ShapeType() != TopAbs_EDGE ||
+ !algo->isDegenerated( TopoDS::Edge( subS.Current() ))))
+ ret = false;
+ }
+#ifdef PRINT_WHO_COMPUTE_WHAT
+ for (subS.ReInit(); subS.More(); subS.Next())
+ {
+ const std::list <const SMESHDS_Hypothesis *> & hyps =
+ _algo->GetUsedHypothesis( *_father, _subShape );
+ SMESH_Comment hypStr;
+ if ( !hyps.empty() )
+ {
+ hypStr << hyps.front()->GetName() << " ";
+ ((SMESHDS_Hypothesis*)hyps.front())->SaveTo( hypStr.Stream() );
+ hypStr << " ";
+ }
+ cout << _algo->GetName()
+ << " " << _father->GetSubMesh( subS.Current() )->GetId()
+ << " " << hypStr << endl;
+ }
+#endif
+ // Set _computeError
+ if ( !ret && !isComputeErrorSet )
+ {
+ for ( subS.ReInit(); subS.More(); subS.Next() )
+ {
+ SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
+ if ( !sm->IsMeshComputed() )
+ {
+ if ( !sm->_computeError )
+ sm->_computeError = SMESH_ComputeError::New();
+ if ( sm->_computeError->IsOK() )
+ sm->_computeError->myName = COMPERR_ALGO_FAILED;
+ sm->_computeState = FAILED_TO_COMPUTE;
+ sm->_computeError->myAlgo = algo;
+ }
+ }
+ }
+ if ( ret && _computeError && _computeError->myName != COMPERR_WARNING )
+ {
+ _computeError.reset();
+ }
+
+ // transform errors into warnings if it is caused by mesh edition (imp 0023068)
+ if (!ret && _father->GetIsModified() )
+ {
+ for (subS.ReInit(); subS.More(); subS.Next())
+ {
+ SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
+ if ( !sm->IsMeshComputed() && sm->_computeError )
+ {
+ // check if there is a VERTEX w/o nodes
+ // with READY_TO_COMPUTE state (after MergeNodes())
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,false);
+ while ( smIt->more() )
+ {
+ SMESH_subMesh * vertSM = smIt->next();
+ if ( vertSM->_subShape.ShapeType() != TopAbs_VERTEX ) break;
+ if ( vertSM->GetComputeState() == READY_TO_COMPUTE )
+ {
+ SMESHDS_SubMesh * ds = vertSM->GetSubMeshDS();
+ if ( !ds || ds->NbNodes() == 0 )
+ {
+ sm->_computeState = READY_TO_COMPUTE;
+ sm->_computeError->myName = COMPERR_WARNING;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // send event SUBMESH_COMPUTED
+ if ( ret ) {
+ if ( !algo->NeedDiscreteBoundary() )
+ // send SUBMESH_COMPUTED to dependants of all sub-meshes of shape
+ for (subS.ReInit(); subS.More(); subS.Next())
+ {
+ SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,false);
+ while ( smIt->more() ) {
+ sm = smIt->next();
+ if ( sm->GetSubShape().ShapeType() == TopAbs_VERTEX )
+ sm->updateDependantsState( SUBMESH_COMPUTED );
+ else
+ break;
+ }
+ }
+ else
+ updateDependantsState( SUBMESH_COMPUTED );
+ }
+ }
+ break;
+ case COMPUTE_CANCELED: // nothing to do
+ break;
+ case CLEAN:
+ cleanDependants();
+ removeSubMeshElementsAndNodes();
+ _computeState = NOT_READY;
+ algo = GetAlgo();
+ if (algo)
+ {
+ ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
+ if (ret)
+ _computeState = READY_TO_COMPUTE;
+ else
+ setAlgoState(MISSING_HYP);
+ }
+ break;
+ case SUBMESH_COMPUTED: // nothing to do
+ break;
+ case SUBMESH_RESTORED:
+ // check if a mesh is already computed that may
+ // happen after retrieval from a file
+ ComputeStateEngine( CHECK_COMPUTE_STATE );
+ ComputeSubMeshStateEngine( SUBMESH_RESTORED );
+ algo = GetAlgo();
+ if (algo) algo->SubmeshRestored( this );
+ break;
+ case MESH_ENTITY_REMOVED:
+ break;
+ case SUBMESH_LOADED:
+ loadDependentMeshes();
+ ComputeSubMeshStateEngine( SUBMESH_LOADED );
+ //break;
+ case CHECK_COMPUTE_STATE:
+ if ( IsMeshComputed() )
+ _computeState = COMPUTE_OK;
+ else if ( _computeError && _computeError->IsKO() )
+ _computeState = FAILED_TO_COMPUTE;
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ break;
+
+ // ----------------------------------------------------------------------
+
+ case COMPUTE_OK:
+ switch (event)
+ {
+ case MODIF_ALGO_STATE:
+ ComputeStateEngine( CLEAN );
+ algo = GetAlgo();
+ if (algo && !algo->NeedDiscreteBoundary())
+ cleanDependsOn( algo ); // clean sub-meshes with event CLEAN
+ break;
+ case COMPUTE: // nothing to do
+ break;
+ case COMPUTE_CANCELED: // nothing to do
+ break;
+ case CLEAN:
+ cleanDependants(); // clean sub-meshes, dependent on this one, with event CLEAN
+ removeSubMeshElementsAndNodes();
+ _computeState = NOT_READY;
+ if ( _algoState == HYP_OK )
+ _computeState = READY_TO_COMPUTE;
+ break;
+ case SUBMESH_COMPUTED: // nothing to do
+ break;
+ case SUBMESH_RESTORED:
+ ComputeStateEngine( CHECK_COMPUTE_STATE );
+ ComputeSubMeshStateEngine( SUBMESH_RESTORED );
+ algo = GetAlgo();
+ if (algo) algo->SubmeshRestored( this );
+ break;
+ case MESH_ENTITY_REMOVED:
+ updateDependantsState ( CHECK_COMPUTE_STATE );
+ ComputeStateEngine ( CHECK_COMPUTE_STATE );
+ ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+ break;
+ case CHECK_COMPUTE_STATE:
+ if ( !IsMeshComputed() ) {
+ if (_algoState == HYP_OK)
+ _computeState = READY_TO_COMPUTE;
+ else
+ _computeState = NOT_READY;
+ }
+ break;
+ case SUBMESH_LOADED:
+ // already treated event, thanks to which _computeState == COMPUTE_OK
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ break;
+
+ // ----------------------------------------------------------------------
+
+ case FAILED_TO_COMPUTE:
+ switch (event)
+ {
+ case MODIF_ALGO_STATE:
+ if ( !IsEmpty() )
+ ComputeStateEngine( CLEAN );
+ algo = GetAlgo();
+ if (algo && !algo->NeedDiscreteBoundary())
+ cleanDependsOn( algo ); // clean sub-meshes with event CLEAN
+ if (_algoState == HYP_OK)
+ _computeState = READY_TO_COMPUTE;
+ else
+ _computeState = NOT_READY;
+ break;
+ case COMPUTE: // nothing to do
+ case COMPUTE_SUBMESH:
+ break;
+ case COMPUTE_CANCELED:
+ {
+ algo = GetAlgo();
+ algo->CancelCompute();
+ }
+ break;
+ case CLEAN:
+ cleanDependants(); // submeshes dependent on me should be cleaned as well
+ removeSubMeshElementsAndNodes();
+ break;
+ case SUBMESH_COMPUTED: // allow retry compute
+ if ( IsEmpty() ) // 23061
+ {
+ if (_algoState == HYP_OK)
+ _computeState = READY_TO_COMPUTE;
+ else
+ _computeState = NOT_READY;
+ }
+ break;
+ case SUBMESH_RESTORED:
+ ComputeSubMeshStateEngine( SUBMESH_RESTORED );
+ break;
+ case MESH_ENTITY_REMOVED:
+ break;
+ case CHECK_COMPUTE_STATE:
+ if ( IsMeshComputed() )
+ _computeState = COMPUTE_OK;
+ else
+ if (_algoState == HYP_OK)
+ _computeState = READY_TO_COMPUTE;
+ else
+ _computeState = NOT_READY;
+ break;
+ // case SUBMESH_LOADED:
+ // break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ break;
+
+ // ----------------------------------------------------------------------
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ notifyListenersOnEvent( event, COMPUTE_EVENT );
+
+ return ret;