+ // **** les retour des evenement shape sont significatifs
+ // (add ou remove fait ou non)
+ // le retour des evenement father n'indiquent pas que add ou remove fait
+
+ SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
+
+ SMESHDS_Mesh* meshDS =_father->GetMeshDS();
+ SMESH_Algo* algo = 0;
+ _algo = 0;
+
+ if (_subShape.ShapeType() == TopAbs_VERTEX )
+ {
+ if ( anHyp->GetDim() != 0) {
+ if (event == ADD_HYP || event == ADD_ALGO)
+ return SMESH_Hypothesis::HYP_BAD_DIM;
+ else
+ return SMESH_Hypothesis::HYP_OK;
+ }
+ // 0D hypothesis
+ else if ( _algoState == HYP_OK ) {
+ // update default _algoState
+ if ( event != REMOVE_FATHER_ALGO )
+ {
+ _algoState = NO_ALGO;
+ algo = GetAlgo();
+ if ( algo ) {
+ _algoState = MISSING_HYP;
+ if ( event == REMOVE_FATHER_HYP ||
+ algo->CheckHypothesis(*_father,_subShape, aux_ret))
+ _algoState = HYP_OK;
+ }
+ }
+ }
+ }
+
+ int oldAlgoState = _algoState;
+ bool modifiedHyp = (event == MODIF_HYP); // if set to true, force event MODIF_ALGO_STATE
+ SMESH_Algo* algoRequiringCleaning = 0;
+
+ bool isApplicableHyp = IsApplicableHypotesis( anHyp );
+
+ if (event == ADD_ALGO || event == ADD_FATHER_ALGO)
+ {
+ // -------------------------------------------
+ // check if a shape needed by algo is present
+ // -------------------------------------------
+ algo = static_cast< SMESH_Algo* >( anHyp );
+ if ( !_father->HasShapeToMesh() && algo->NeedShape() )
+ return SMESH_Hypothesis::HYP_NEED_SHAPE;
+ // ----------------------
+ // check mesh conformity
+ // ----------------------
+ if (isApplicableHyp && !_father->IsNotConformAllowed() && !IsConform( algo ))
+ return SMESH_Hypothesis::HYP_NOTCONFORM;
+
+ // check if all-dimensional algo is hidden by other local one
+ if ( event == ADD_ALGO ) {
+ SMESH_HypoFilter filter( SMESH_HypoFilter::HasType( algo->GetType() ));
+ filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+1 ));
+ filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+2 ));
+ if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis( this, filter, true ))
+ if ( !curAlgo->NeedDiscreteBoundary() )
+ algoRequiringCleaning = curAlgo;
+ }
+ }
+
+ // ----------------------------------
+ // add a hypothesis to DS if possible
+ // ----------------------------------
+ if (event == ADD_HYP || event == ADD_ALGO)
+ {
+ if ( ! CanAddHypothesis( anHyp )) // check dimension
+ return SMESH_Hypothesis::HYP_BAD_DIM;
+
+ if ( !anHyp->IsAuxiliary() && getSimilarAttached( _subShape, anHyp ) )
+ return SMESH_Hypothesis::HYP_ALREADY_EXIST;
+
+ if ( !meshDS->AddHypothesis(_subShape, anHyp))
+ return SMESH_Hypothesis::HYP_ALREADY_EXIST;
+ }
+
+ // --------------------------
+ // remove a hypothesis from DS
+ // --------------------------
+ if (event == REMOVE_HYP || event == REMOVE_ALGO)
+ {
+ if (!meshDS->RemoveHypothesis(_subShape, anHyp))
+ return SMESH_Hypothesis::HYP_OK; // nothing changes
+
+ if (event == REMOVE_ALGO)
+ {
+ algo = dynamic_cast<SMESH_Algo*> (anHyp);
+ if (!algo->NeedDiscreteBoundary())
+ algoRequiringCleaning = algo;
+ }
+ }
+
+ // ------------------
+ // analyse algo state
+ // ------------------
+ if (!isApplicableHyp)
+ return ret; // not applicable hypotheses do not change algo state
+
+ if (( algo = GetAlgo()))
+ algo->InitComputeError();
+
+ switch (_algoState)
+ {
+
+ // ----------------------------------------------------------------------
+
+ case NO_ALGO:
+ switch (event) {
+ case ADD_HYP:
+ break;
+ case ADD_ALGO: {
+ algo = GetAlgo();
+ ASSERT(algo);
+ if (algo->CheckHypothesis((*_father),_subShape, aux_ret))
+ setAlgoState(HYP_OK);
+ else if ( algo->IsStatusFatal( aux_ret )) {
+ meshDS->RemoveHypothesis(_subShape, anHyp);
+ ret = aux_ret;
+ }
+ else
+ setAlgoState(MISSING_HYP);
+ break;
+ }
+ case REMOVE_HYP:
+ case REMOVE_ALGO:
+ case ADD_FATHER_HYP:
+ break;
+ case ADD_FATHER_ALGO: { // Algo just added in father
+ algo = GetAlgo();
+ ASSERT(algo);
+ if ( algo == anHyp ) {
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret))
+ setAlgoState(HYP_OK);
+ else
+ setAlgoState(MISSING_HYP);
+ }
+ break;
+ }
+ case REMOVE_FATHER_HYP:
+ break;
+ case REMOVE_FATHER_ALGO: {
+ algo = GetAlgo();
+ if (algo)
+ {
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+ setAlgoState(HYP_OK);
+ else
+ setAlgoState(MISSING_HYP);
+ }
+ break;
+ }
+ case MODIF_HYP: break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ break;
+
+ // ----------------------------------------------------------------------
+
+ case MISSING_HYP:
+ switch (event)
+ {
+ case ADD_HYP: {
+ algo = GetAlgo();
+ ASSERT(algo);
+ if ( algo->CheckHypothesis((*_father),_subShape, ret ))
+ setAlgoState(HYP_OK);
+ if (SMESH_Hypothesis::IsStatusFatal( ret ))
+ meshDS->RemoveHypothesis(_subShape, anHyp);
+ else if (!_father->IsUsedHypothesis( anHyp, this ))
+ {
+ meshDS->RemoveHypothesis(_subShape, anHyp);
+ ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+ }
+ break;
+ }
+ case ADD_ALGO: { //already existing algo : on father ?
+ algo = GetAlgo();
+ ASSERT(algo);
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status
+ setAlgoState(HYP_OK);
+ else if ( algo->IsStatusFatal( aux_ret )) {
+ meshDS->RemoveHypothesis(_subShape, anHyp);
+ ret = aux_ret;
+ }
+ else
+ setAlgoState(MISSING_HYP);
+ break;
+ }
+ case REMOVE_HYP:
+ break;
+ case REMOVE_ALGO: { // perhaps a father algo applies ?
+ algo = GetAlgo();
+ if (algo == NULL) // no more algo applying on sub-shape...
+ {
+ setAlgoState(NO_ALGO);
+ }
+ else
+ {
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+ setAlgoState(HYP_OK);
+ else
+ setAlgoState(MISSING_HYP);
+ }
+ break;
+ }
+ case MODIF_HYP: // assigned hypothesis value may become good
+ case ADD_FATHER_HYP: {
+ algo = GetAlgo();
+ ASSERT(algo);
+ if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+ setAlgoState(HYP_OK);
+ else
+ setAlgoState(MISSING_HYP);
+ break;
+ }
+ case ADD_FATHER_ALGO: { // new father algo
+ algo = GetAlgo();
+ 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 = GetAlgo();
+ 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 = GetAlgo();
+ 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 = GetAlgo();
+ 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( this, f, true );
+ if (prevAlgo &&
+ string(algo->GetName()) != string(prevAlgo->GetName()) )
+ modifiedHyp = true;
+ }
+ else
+ setAlgoState(MISSING_HYP);
+ break;
+ }
+ case REMOVE_HYP: {
+ algo = GetAlgo();
+ 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 = GetAlgo();
+ if (algo == NULL) // no more algo applying on sub-shape...
+ {
+ 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 = GetAlgo();
+ 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 = GetAlgo();
+ 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( this, f, true );
+ if (prevAlgo &&
+ string(algo->GetName()) != string(prevAlgo->GetName()) )
+ modifiedHyp = true;
+ }
+ else
+ setAlgoState(MISSING_HYP);
+ }
+ break;
+ }
+ case REMOVE_FATHER_HYP: {
+ algo = GetAlgo();
+ 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: {
+ // IPAL21346. Edges not removed when Netgen 1d-2d is removed from a SOLID.
+ // CLEAN was not called at event REMOVE_ALGO because the algo is not applicable to SOLID.
+ algo = dynamic_cast<SMESH_Algo*> (anHyp);
+ if (!algo->NeedDiscreteBoundary())
+ algoRequiringCleaning = algo;
+ algo = GetAlgo();
+ 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();
+ const std::vector< SMESH_subMesh * > & ancestors = GetAncestors();
+ for ( size_t iA = 0; ( ret == SMESH_Hypothesis::HYP_OK && iA < ancestors.size()); ++iA ) {
+ if ( SMESH_Algo* upperAlgo = ancestors[ iA ]->GetAlgo() )
+ if ( !upperAlgo->NeedDiscreteBoundary() && !upperAlgo->SupportSubmeshes())
+ ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO;
+ }
+ // is algo hiding?
+ if ( ret == SMESH_Hypothesis::HYP_OK &&
+ !algo->NeedDiscreteBoundary() &&
+ !algo->SupportSubmeshes())
+ {
+ TopoDS_Shape algoAssignedTo, otherAssignedTo;
+ gen->GetAlgo( this, &algoAssignedTo );
+ 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( i_sm->second, &otherAssignedTo ) &&
+ SMESH_MesherHelper::IsSubShape( /*sub=*/otherAssignedTo, /*main=*/algoAssignedTo ))
+ ret = SMESH_Hypothesis::HYP_HIDING_ALGO;
+ }
+ }
+
+ if ( _algo ) { // get an error description set by _algo->CheckHypothesis()
+ _computeError = _algo->GetComputeError();
+ _algo->InitComputeError();
+ }
+
+ bool stateChange = ( _algoState != oldAlgoState );
+
+ if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK
+ algo->SetEventListener( this );
+
+ if ( event == REMOVE_ALGO || event == REMOVE_FATHER_ALGO )
+ _algo = 0;
+
+ 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 ( algoRequiringCleaning ) {
+ // added or removed algo is all-dimensional
+ ComputeStateEngine( CLEAN );
+ cleanDependsOn( algoRequiringCleaning );
+ ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+ }
+
+ if ( stateChange || modifiedHyp )
+ ComputeStateEngine( MODIF_ALGO_STATE );
+
+ _realComputeCost = ( _algoState == HYP_OK ) ? computeCost() : 0;
+
+ 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 NeedDiscreteBoundary(): because mesh made
+ // on a sub-shape will be ignored by theAlgo
+ if ( theAlgo->NeedDiscreteBoundary() ||
+ !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
+ const std::vector< SMESH_subMesh * > & ancestors = GetAncestors();
+ for ( size_t iA = 0; iA < ancestors.size(); ++iA )
+ {
+ const TopoDS_Shape& adjacent = ancestors[ iA ]->GetSubShape();
+ if ( _subShape.IsSame( adjacent )) continue;
+ if ( adjacent.ShapeType() != _subShape.ShapeType())
+ break;
+
+ // check algo attached to smAdjacent
+ SMESH_Algo * algo = ancestors[ iA ]->GetAlgo();
+ if (algo &&
+ !algo->NeedDiscreteBoundary() &&
+ algo->OnlyUnaryInput())
+ return false; // NOT CONFORM MESH WILL BE PRODUCED
+ }
+ }
+
+ return true;