-// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
int oldAlgoState = _algoState;
bool modifiedHyp = (event == MODIF_HYP); // if set to true, force event MODIF_ALGO_STATE
- bool needFullClean = false, subMeshesSupported = false;
+ SMESH_Algo* algoRequiringCleaning = 0;
bool isApplicableHyp = IsApplicableHypotesis( anHyp );
filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+1 ));
filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+2 ));
if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis(_subShape, filter, true ))
- needFullClean = ( !curAlgo->NeedDiscreteBoundary() );
+ if ( !curAlgo->NeedDiscreteBoundary() )
+ algoRequiringCleaning = curAlgo;
}
}
{
algo = dynamic_cast<SMESH_Algo*> (anHyp);
if (!algo->NeedDiscreteBoundary())
- {
- // clean all mesh in the tree of the current submesh;
- // we must perform it now because later
- // we will have no information about the type of the removed algo
- needFullClean = true;
- subMeshesSupported = algo->SupportSubmeshes();
- }
+ algoRequiringCleaning = algo;
}
}
// 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())
- {
- needFullClean = true;
- subMeshesSupported = algo->SupportSubmeshes();
- }
+ algoRequiringCleaning = algo;
algo = GetAlgo();
if (algo == NULL) // no more applying algo on father
{
}
}
- if ( needFullClean ) {
+ if ( algoRequiringCleaning ) {
// added or removed algo is all-dimensional
ComputeStateEngine( CLEAN );
- cleanDependsOn( subMeshesSupported );
+ cleanDependsOn( algoRequiringCleaning );
ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
}
//================================================================================
/*!
* \brief Remove elements from sub-meshes.
- * \param keepSupportedsubMeshes - if true, the sub-meshes computed using more
- * local algorithms are not cleaned
+ * \param algoRequiringCleaning - an all-dimensional algorithm whose presence
+ * causes the cleaning.
*/
//================================================================================
-void SMESH_subMesh::cleanDependsOn( bool keepSupportedsubMeshes )
+void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ )
{
- if ( _father->NbNodes() == 0 ) return;
-
SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,
/*complexShapeFirst=*/true);
- if ( !keepSupportedsubMeshes )
+ if ( _father->NbNodes() == 0 )
+ {
+ while ( smIt->more() )
+ smIt->next()->ComputeStateEngine(CHECK_COMPUTE_STATE);
+ }
+ else if ( !algoRequiringCleaning || !algoRequiringCleaning->SupportSubmeshes() )
{
while ( smIt->more() )
smIt->next()->ComputeStateEngine(CLEAN);
}
- else
+ else if ( algoRequiringCleaning && algoRequiringCleaning->SupportSubmeshes() )
{
+ SMESHDS_Mesh* meshDS = _father->GetMeshDS();
+
// find sub-meshes to keep elements on
set< SMESH_subMesh* > smToKeep;
- SMESHDS_Mesh* meshDS = _father->GetMeshDS();
+ TopAbs_ShapeEnum prevShapeType = TopAbs_SHAPE;
+ bool toKeepPrevShapeType = false;
while ( smIt->more() )
{
SMESH_subMesh* sm = smIt->next();
- if ( sm->IsEmpty() ) continue;
-
- // look for an algo assigned to sm
- bool algoFound = false;
- const list<const SMESHDS_Hypothesis*>& hyps = meshDS->GetHypothesis( sm->_subShape );
- list<const SMESHDS_Hypothesis*>::const_iterator h = hyps.begin();
- for ( ; ( !algoFound && h != hyps.end() ); ++h )
- algoFound = ((*h)->GetType() != SMESHDS_Hypothesis::PARAM_ALGO );
-
- // remember all sub-meshes of sm
- if ( algoFound )
+ sm->ComputeStateEngine(CHECK_COMPUTE_STATE);
+ if ( !sm->IsEmpty() )
{
- SMESH_subMeshIteratorPtr smIt2 = getDependsOnIterator(false,true);
- while ( smIt2->more() )
- smToKeep.insert( smIt2->next() );
+ const bool sameShapeType = ( prevShapeType == sm->GetSubShape().ShapeType() );
+ bool keepSubMeshes = ( sameShapeType && toKeepPrevShapeType );
+ if ( !sameShapeType )
+ {
+ // check if the algo allows presence of global algos of dimension the algo
+ // can generate it-self
+ int shapeDim = SMESH_Gen::GetShapeDim( sm->GetSubShape() );
+ keepSubMeshes = algoRequiringCleaning->NeedLowerHyps( shapeDim );
+ prevShapeType = sm->GetSubShape().ShapeType();
+ toKeepPrevShapeType = keepSubMeshes;
+ }
+ if ( !keepSubMeshes )
+ {
+ // look for an algo assigned to sm
+ bool algoFound = false;
+ const list<const SMESHDS_Hypothesis*>& hyps = meshDS->GetHypothesis( sm->_subShape );
+ list<const SMESHDS_Hypothesis*>::const_iterator h = hyps.begin();
+ for ( ; ( !algoFound && h != hyps.end() ); ++h )
+ algoFound = ((*h)->GetType() != SMESHDS_Hypothesis::PARAM_ALGO );
+ keepSubMeshes = algoFound;
+ }
+ // remember all sub-meshes of sm
+ if ( keepSubMeshes )
+ {
+ SMESH_subMeshIteratorPtr smIt2 = getDependsOnIterator(false,true);
+ while ( smIt2->more() )
+ smToKeep.insert( smIt2->next() );
+ }
}
}
// remove elements
switch ( event ) {
case MODIF_ALGO_STATE:
case COMPUTE:
+ case COMPUTE_SUBMESH:
//case COMPUTE_CANCELED:
case CLEAN:
//case SUBMESH_COMPUTED:
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 ( smDS && smDS->NbNodes() )
+ {
if ( event == CLEAN ) {
cleanDependants();
cleanSubMesh( this );
else
_computeState = COMPUTE_OK;
}
- else if ( event == COMPUTE && !_alwaysComputed ) {
+ 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()) ) {
case MODIF_ALGO_STATE:
algo = GetAlgo();
if (algo && !algo->NeedDiscreteBoundary())
- cleanDependsOn( algo->SupportSubmeshes() ); // clean sub-meshes with event CLEAN
+ 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;
-#ifdef WITH_SMESH_CANCEL_COMPUTE
- case COMPUTE_CANCELED: // nothing to do
+ case COMPUTE_CANCELED: // nothing to do
break;
-#endif
case CLEAN:
cleanDependants();
removeSubMeshElementsAndNodes();
if (algo)
{
if (!algo->NeedDiscreteBoundary())
- cleanDependsOn( algo->SupportSubmeshes() ); // clean sub-meshes with event CLEAN
+ cleanDependsOn( algo ); // clean sub-meshes with event CLEAN
if ( _algoState == HYP_OK )
_computeState = READY_TO_COMPUTE;
}
break;
case COMPUTE:
+ case COMPUTE_SUBMESH:
{
algo = GetAlgo();
ASSERT(algo);
// check submeshes needed
if (_father->HasShapeToMesh() ) {
bool subComputed = false, subFailed = false;
- if (!algo->OnlyUnaryInput())
- shape = getCollection( gen, algo, subComputed, subFailed );
- else
+ if (!algo->OnlyUnaryInput()) {
+ if ( event == COMPUTE /*&&
+ ( algo->NeedDiscreteBoundary() || algo->SupportSubmeshes() )*/)
+ shape = getCollection( gen, algo, subComputed, subFailed );
+ else
+ subComputed = SubMeshesComputed( & subFailed );
+ }
+ else {
subComputed = SubMeshesComputed();
+ }
ret = ( algo->NeedDiscreteBoundary() ? subComputed :
algo->SupportSubmeshes() ? !subFailed :
( !subComputed || _father->IsNotConformAllowed() ));
}
}
break;
-#ifdef WITH_SMESH_CANCEL_COMPUTE
case COMPUTE_CANCELED: // nothing to do
break;
-#endif
case CLEAN:
cleanDependants();
removeSubMeshElementsAndNodes();
ComputeStateEngine( CLEAN );
algo = GetAlgo();
if (algo && !algo->NeedDiscreteBoundary())
- cleanDependsOn( algo->SupportSubmeshes() ); // clean sub-meshes with event CLEAN
+ cleanDependsOn( algo ); // clean sub-meshes with event CLEAN
break;
case COMPUTE: // nothing to do
break;
-#ifdef WITH_SMESH_CANCEL_COMPUTE
- case COMPUTE_CANCELED: // nothing to do
+ case COMPUTE_CANCELED: // nothing to do
break;
-#endif
case CLEAN:
cleanDependants(); // clean sub-meshes, dependant on this one, with event CLEAN
removeSubMeshElementsAndNodes();
ComputeStateEngine( CLEAN );
algo = GetAlgo();
if (algo && !algo->NeedDiscreteBoundary())
- cleanDependsOn( algo->SupportSubmeshes() ); // clean sub-meshes with event CLEAN
+ 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: // nothing to do
+ case COMPUTE_SUBMESH:
break;
case COMPUTE_CANCELED:
{
const event_type eventType,
SMESH_Hypothesis* hyp)
{
- map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.begin();
- for ( ; l_d != _eventListeners.end(); )
+ list< pair< EventListener*, EventListenerData* > > eventListeners( _eventListeners.begin(),
+ _eventListeners.end());
+ list< pair< EventListener*, EventListenerData* > >::iterator l_d = eventListeners.begin();
+ for ( ; l_d != eventListeners.end(); ++l_d )
{
- std::pair< EventListener*, EventListenerData* > li_da = *l_d++; /* copy to enable removal
- of a listener from
- _eventListeners by
- its ProcessEvent() */
+ std::pair< EventListener*, EventListenerData* > li_da = *l_d;
+ if ( !_eventListeners.count( li_da.first )) continue;
+
if ( li_da.first->myBusySM.insert( this ).second )
{
- const size_t nbListenersBefore = _eventListeners.size();
+ const bool isDeletable = li_da.first->IsDeletable();
+
li_da.first->ProcessEvent( event, eventType, this, li_da.second, hyp );
- if ( nbListenersBefore == _eventListeners.size() )
- li_da.first->myBusySM.erase( this ); // a listener hopefully not removed
+
+ if ( !isDeletable || !_eventListeners.count( li_da.first ))
+ li_da.first->myBusySM.erase( this ); // a listener is hopefully not dead
}
}
}
(*smIt)->ComputeStateEngine( event );
break;
case SMESH_subMesh::COMPUTE:
+ case SMESH_subMesh::COMPUTE_SUBMESH:
if ( subMesh->GetComputeState() == SMESH_subMesh::COMPUTE_OK )
for ( ; smIt != smEnd; ++ smIt)
(*smIt)->ComputeStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );