+ case ADD_FATHER_ALGO: { // new father algo
+ algo = gen->GetAlgo((*_father), _subShape);
+ ASSERT( algo );
+ if ( algo == anHyp ) {
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+ SetAlgoState(HYP_OK);
+ else
+ SetAlgoState(MISSING_HYP);
+ }
+ break;
+ }
+ case REMOVE_FATHER_HYP: // nothing to do
+ break;
+ case REMOVE_FATHER_ALGO: {
+ algo = gen->GetAlgo((*_father), _subShape);
+ if (algo == NULL) // no more applying algo on father
+ {
+ SetAlgoState(NO_ALGO);
+ }
+ else
+ {
+ if ( algo->CheckHypothesis((*_father),_subShape , aux_ret ))
+ SetAlgoState(HYP_OK);
+ else
+ SetAlgoState(MISSING_HYP);
+ }
+ break;
+ }
+ default:
+ ASSERT(0);
+ break;
+ }
+ break;
+
+ // ----------------------------------------------------------------------
+
+ case HYP_OK:
+ switch (event)
+ {
+ case ADD_HYP: {
+ algo = gen->GetAlgo((*_father), _subShape);
+ ASSERT(algo);
+ if (!algo->CheckHypothesis((*_father),_subShape, ret ))
+ {
+ if ( !SMESH_Hypothesis::IsStatusFatal( ret ))
+ // ret should be fatal: anHyp was not added
+ ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+ }
+ else if (!_father->IsUsedHypothesis( anHyp, this ))
+ ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+
+ if (SMESH_Hypothesis::IsStatusFatal( ret ))
+ {
+ MESSAGE("do not add extra hypothesis");
+ meshDS->RemoveHypothesis(_subShape, anHyp);
+ }
+ else
+ {
+ modifiedHyp = true;
+ }
+ break;
+ }
+ case ADD_ALGO: { //already existing algo : on father ?
+ algo = gen->GetAlgo((*_father), _subShape);
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+ // check if algo changes
+ SMESH_HypoFilter f;
+ f.Init( SMESH_HypoFilter::IsAlgo() );
+ f.And( SMESH_HypoFilter::IsApplicableTo( _subShape ));
+ f.AndNot( SMESH_HypoFilter::Is( algo ));
+ const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true );
+ if (prevAlgo &&
+ string(algo->GetName()) != string(prevAlgo->GetName()) )
+ modifiedHyp = true;
+ }
+ else
+ SetAlgoState(MISSING_HYP);
+ break;
+ }
+ case REMOVE_HYP: {
+ algo = gen->GetAlgo((*_father), _subShape);
+ ASSERT(algo);
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+ SetAlgoState(HYP_OK);
+ else
+ SetAlgoState(MISSING_HYP);
+ modifiedHyp = true;
+ break;
+ }
+ case REMOVE_ALGO: { // perhaps a father algo applies ?
+ algo = gen->GetAlgo((*_father), _subShape);
+ if (algo == NULL) // no more algo applying on subShape...
+ {
+ SetAlgoState(NO_ALGO);
+ }
+ else
+ {
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+ // check if algo remains
+ if ( anHyp != algo && strcmp( anHyp->GetName(), algo->GetName()) )
+ modifiedHyp = true;
+ }
+ else
+ SetAlgoState(MISSING_HYP);
+ }
+ break;
+ }
+ case MODIF_HYP: // hypothesis value may become bad
+ case ADD_FATHER_HYP: { // new father hypothesis ?
+ algo = gen->GetAlgo((*_father), _subShape);
+ ASSERT(algo);
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+ {
+ if (_father->IsUsedHypothesis( anHyp, this )) // new Hyp
+ modifiedHyp = true;
+ }
+ else
+ SetAlgoState(MISSING_HYP);
+ break;
+ }
+ case ADD_FATHER_ALGO: {
+ algo = gen->GetAlgo((*_father), _subShape);
+ if ( algo == anHyp ) { // a new algo on father
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+ // check if algo changes
+ SMESH_HypoFilter f;
+ f.Init( SMESH_HypoFilter::IsAlgo() );
+ f.And( SMESH_HypoFilter::IsApplicableTo( _subShape ));
+ f.AndNot( SMESH_HypoFilter::Is( algo ));
+ const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true );
+ if (prevAlgo &&
+ string(algo->GetName()) != string(prevAlgo->GetName()) )
+ modifiedHyp = true;
+ }
+ else
+ SetAlgoState(MISSING_HYP);
+ }
+ break;
+ }
+ case REMOVE_FATHER_HYP: {
+ algo = gen->GetAlgo((*_father), _subShape);
+ ASSERT(algo);
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+ // is there the same local hyp or maybe a new father algo applied?
+ if ( !GetSimilarAttached( _subShape, anHyp ) )
+ modifiedHyp = true;
+ }
+ else
+ SetAlgoState(MISSING_HYP);
+ break;
+ }
+ case REMOVE_FATHER_ALGO: {
+ algo = gen->GetAlgo((*_father), _subShape);
+ if (algo == NULL) // no more applying algo on father
+ {
+ SetAlgoState(NO_ALGO);
+ }
+ else
+ {
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+ // check if algo changes
+ if ( string(algo->GetName()) != string( anHyp->GetName()) )
+ modifiedHyp = true;
+ }
+ else
+ SetAlgoState(MISSING_HYP);
+ }
+ break;
+ }
+ default:
+ ASSERT(0);
+ break;
+ }
+ break;
+
+ // ----------------------------------------------------------------------
+
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ // detect algorithm hiding
+ //
+ if ( ret == SMESH_Hypothesis::HYP_OK &&
+ ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) &&
+ algo->GetName() == anHyp->GetName() )
+ {
+ // is algo hidden?
+ SMESH_Gen* gen = _father->GetGen();
+ TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
+ for ( ; ( ret == SMESH_Hypothesis::HYP_OK && it.More()); it.Next() ) {
+ if ( SMESH_Algo* upperAlgo = gen->GetAlgo( *_father, it.Value() ))
+ if ( !upperAlgo->NeedDescretBoundary() && !upperAlgo->SupportSubmeshes())
+ ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO;
+ }
+ // is algo hiding?
+ if ( ret == SMESH_Hypothesis::HYP_OK &&
+ !algo->NeedDescretBoundary() &&
+ !algo->SupportSubmeshes()) {
+ map<int, SMESH_subMesh*>::reverse_iterator i_sm = _mapDepend.rbegin();
+ for ( ; ( ret == SMESH_Hypothesis::HYP_OK && i_sm != _mapDepend.rend()) ; ++i_sm )
+ if ( gen->GetAlgo( *_father, i_sm->second->_subShape ))
+ ret = SMESH_Hypothesis::HYP_HIDING_ALGO;
+ }
+ }
+
+ bool stateChange = ( _algoState != oldAlgoState );
+
+ if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK
+ algo->SetEventListener( this );
+
+ NotifyListenersOnEvent( event, ALGO_EVENT, anHyp );
+
+ if ( stateChange && oldAlgoState == HYP_OK ) { // hyp becomes KO
+ DeleteOwnListeners();
+ SetIsAlwaysComputed( false );
+ if (_subShape.ShapeType() == TopAbs_VERTEX ) {
+ // restore default states
+ _algoState = HYP_OK;
+ _computeState = READY_TO_COMPUTE;
+ }
+ }
+
+ if ( needFullClean ) {
+ // added or removed algo is all-dimensional
+ ComputeStateEngine( CLEAN );
+ CleanDependsOn();
+ ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+ }
+
+ if (stateChange || modifiedHyp)
+ ComputeStateEngine(MODIF_ALGO_STATE);
+
+ return ret;
+}
+
+//=======================================================================
+//function : IsConform
+//purpose : check if a conform mesh will be produced by the Algo
+//=======================================================================
+
+bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
+{
+// MESSAGE( "SMESH_subMesh::IsConform" );
+ if ( !theAlgo ) return false;
+
+ // Suppose that theAlgo is applicable to _subShape, do not check it here
+ //if ( !IsApplicableHypotesis( theAlgo )) return false;
+
+ // check only algo that doesn't NeedDescretBoundary(): because mesh made
+ // on a sub-shape will be ignored by theAlgo
+ if ( theAlgo->NeedDescretBoundary() ||
+ !theAlgo->OnlyUnaryInput() ) // all adjacent shapes will be meshed by this algo?
+ return true;
+
+ SMESH_Gen* gen =_father->GetGen();
+
+ // only local algo is to be checked
+ //if ( gen->IsGlobalHypothesis( theAlgo, *_father ))
+ if ( _subShape.ShapeType() == _father->GetMeshDS()->ShapeToMesh().ShapeType() )
+ return true;
+
+ // check algo attached to adjacent shapes
+
+ // loop on one level down sub-meshes
+ TopoDS_Iterator itsub( _subShape );
+ for (; itsub.More(); itsub.Next())
+ {
+ // loop on adjacent subShapes
+ TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( itsub.Value() ));
+ for (; it.More(); it.Next())
+ {
+ const TopoDS_Shape& adjacent = it.Value();
+ if ( _subShape.IsSame( adjacent )) continue;
+ if ( adjacent.ShapeType() != _subShape.ShapeType())
+ break;
+
+ // check algo attached to smAdjacent
+ SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent);
+ if (algo &&
+ !algo->NeedDescretBoundary() &&
+ algo->OnlyUnaryInput())
+ return false; // NOT CONFORM MESH WILL BE PRODUCED
+ }
+ }
+
+ return true;
+}
+
+//=============================================================================