X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_subMesh.cxx;h=e87b147c3fb068a431aa755607360a22c7ef35c3;hp=d048ce2b084f84c50483b021403bae449e92e6b0;hb=69f064e1222d71a85b8ac1e11d82e0480b6d6cea;hpb=f5016d85b7b4b88623723027a1585c6414c4dc66 diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index d048ce2b0..e87b147c3 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2014 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 @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -88,22 +88,24 @@ SMESH_subMesh::SMESH_subMesh(int Id, SMESHDS_Mesh * meshDS, const TopoDS_Shape & aSubShape) { - _subShape = aSubShape; - _subMeshDS = meshDS->MeshElements(_subShape); // may be null ... - _father = father; - _Id = Id; - _dependenceAnalysed = _alwaysComputed = false; - - if (_subShape.ShapeType() == TopAbs_VERTEX) - { - _algoState = HYP_OK; - _computeState = READY_TO_COMPUTE; - } - else - { - _algoState = NO_ALGO; - _computeState = NOT_READY; - } + _subShape = aSubShape; + _subMeshDS = meshDS->MeshElements(_subShape); // may be null ... + _father = father; + _Id = Id; + _dependenceAnalysed = _alwaysComputed = false; + _algo = 0; + if (_subShape.ShapeType() == TopAbs_VERTEX) + { + _algoState = HYP_OK; + _computeState = READY_TO_COMPUTE; + } + else + { + _algoState = NO_ALGO; + _computeState = NOT_READY; + } + _computeCost = 0; // how costly is to compute this sub-mesh + _realComputeCost = 0; } //============================================================================= @@ -114,8 +116,6 @@ SMESH_subMesh::SMESH_subMesh(int Id, SMESH_subMesh::~SMESH_subMesh() { - MESSAGE("SMESH_subMesh::~SMESH_subMesh"); - // **** deleteOwnListeners(); } @@ -149,6 +149,17 @@ SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS() */ //============================================================================= +const SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS() const +{ + return ((SMESH_subMesh*) this )->GetSubMeshDS(); +} + +//============================================================================= +/*! + * + */ +//============================================================================= + SMESHDS_SubMesh* SMESH_subMesh::CreateSubMeshDS() { if ( !GetSubMeshDS() ) { @@ -183,7 +194,9 @@ SMESH_subMesh *SMESH_subMesh::GetFirstToCompute() SMESH_Algo* SMESH_subMesh::GetAlgo() const { - return _father->GetGen()->GetAlgo(*_father, _subShape); + if ( !_algo ) + ((SMESH_subMesh*)this)->_algo = _father->GetGen()->GetAlgo(*_father, _subShape); + return _algo; } //================================================================================ @@ -253,15 +266,16 @@ bool SMESH_subMesh::IsMeshComputed() const //============================================================================= /*! - * + * Return true if all sub-meshes have been meshed */ //============================================================================= -bool SMESH_subMesh::subMeshesComputed() +bool SMESH_subMesh::SubMeshesComputed(bool * isFailedToCompute/*=0*/) const { int myDim = SMESH_Gen::GetShapeDim( _subShape ); int dimToCheck = myDim - 1; bool subMeshesComputed = true; + if ( isFailedToCompute ) *isFailedToCompute = false; // check subMeshes with upper dimension => reverse iteration SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true); while ( smIt->more() ) @@ -270,71 +284,119 @@ bool SMESH_subMesh::subMeshesComputed() if ( sm->_alwaysComputed ) continue; const TopoDS_Shape & ss = sm->GetSubShape(); + // MSV 07.04.2006: restrict checking to myDim-1 only. Ex., there is no sense // in checking of existence of edges if the algo needs only faces. Moreover, // degenerated edges may have no submesh, as after computing NETGEN_2D. - int dim = SMESH_Gen::GetShapeDim( ss ); - if (dim < dimToCheck) - break; // the rest subMeshes are all of less dimension + if ( !_algo || _algo->NeedDiscreteBoundary() ) { + int dim = SMESH_Gen::GetShapeDim( ss ); + if (dim < dimToCheck) + break; // the rest subMeshes are all of less dimension + } SMESHDS_SubMesh * ds = sm->GetSubMeshDS(); bool computeOk = (sm->GetComputeState() == COMPUTE_OK || (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes() ))); if (!computeOk) { - int type = ss.ShapeType(); - subMeshesComputed = false; - - switch (type) - { - case TopAbs_COMPOUND: - { - MESSAGE("The not computed sub mesh is a COMPOUND"); - break; - } - case TopAbs_COMPSOLID: - { - MESSAGE("The not computed sub mesh is a COMPSOLID"); - break; - } - case TopAbs_SHELL: - { - MESSAGE("The not computed sub mesh is a SHEL"); - break; - } - case TopAbs_WIRE: - { - MESSAGE("The not computed sub mesh is a WIRE"); - break; - } - case TopAbs_SOLID: - { - MESSAGE("The not computed sub mesh is a SOLID"); - break; - } - case TopAbs_FACE: - { - MESSAGE("The not computed sub mesh is a FACE"); - break; - } - case TopAbs_EDGE: - { - MESSAGE("The not computed sub mesh is a EDGE"); - break; - } - default: - { - MESSAGE("The not computed sub mesh is of unknown type"); - break; - } - } - - break; + if ( isFailedToCompute && !(*isFailedToCompute) ) + *isFailedToCompute = ( sm->GetComputeState() == FAILED_TO_COMPUTE ); + + // int type = ss.ShapeType(); + + // switch (type) + // { + // case TopAbs_COMPOUND: + // { + // MESSAGE("The not computed sub mesh is a COMPOUND"); + // break; + // } + // case TopAbs_COMPSOLID: + // { + // MESSAGE("The not computed sub mesh is a COMPSOLID"); + // break; + // } + // case TopAbs_SHELL: + // { + // MESSAGE("The not computed sub mesh is a SHEL"); + // break; + // } + // case TopAbs_WIRE: + // { + // MESSAGE("The not computed sub mesh is a WIRE"); + // break; + // } + // case TopAbs_SOLID: + // { + // MESSAGE("The not computed sub mesh is a SOLID"); + // break; + // } + // case TopAbs_FACE: + // { + // MESSAGE("The not computed sub mesh is a FACE"); + // break; + // } + // case TopAbs_EDGE: + // { + // MESSAGE("The not computed sub mesh is a EDGE"); + // break; + // } + // default: + // { + // MESSAGE("The not computed sub mesh is of unknown type"); + // break; + // } + // } + + if ( !isFailedToCompute ) + break; } } return subMeshesComputed; } +//================================================================================ +/*! + * \brief Return cost of computing this sub-mesh. If hypotheses are not well defined, + * zero is returned + * \return int - the computation cost in abstract units. + */ +//================================================================================ + +int SMESH_subMesh::GetComputeCost() const +{ + return _realComputeCost; +} + +//================================================================================ +/*! + * \brief Return cost of computing this sub-mesh. The cost depends on the shape type + * and number of sub-meshes this one DependsOn(). + * \return int - the computation cost in abstract units. + */ +//================================================================================ + +int SMESH_subMesh::computeCost() const +{ + if ( !_computeCost ) + { + int computeCost; + switch ( _subShape.ShapeType() ) { + case TopAbs_SOLID: + case TopAbs_SHELL: computeCost = 5000; break; + case TopAbs_FACE: computeCost = 500; break; + case TopAbs_EDGE: computeCost = 2; break; + default: computeCost = 1; + } + SMESH_subMeshIteratorPtr childIt = getDependsOnIterator(/*includeSelf=*/false); + while ( childIt->more() ) + computeCost += childIt->next()->computeCost(); + + ((SMESH_subMesh*)this)->_computeCost = computeCost; + } + return _computeCost; +} + //============================================================================= /*! * @@ -481,6 +543,23 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() return _mapDepend; } +//================================================================================ +/*! + * \brief Return a key for SMESH_subMesh::_mapDepend map + */ +//================================================================================ + +namespace { + int dependsOnMapKey( const SMESH_subMesh* sm ) + { + int type = sm->GetSubShape().ShapeType(); + int ordType = 9 - type; // 2 = Vertex, 8 = CompSolid + int cle = sm->GetId(); + cle += 10000000 * ordType; // sort map by ordType then index + return cle; + } +} + //============================================================================= /*! * For simple Shapes (solid, face, edge): add subMesh into dependence list. @@ -490,10 +569,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() void SMESH_subMesh::insertDependence(const TopoDS_Shape aSubShape) { SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape); - int type = aSubShape.ShapeType(); - int ordType = 9 - type; // 2 = Vertex, 8 = CompSolid - int cle = aSubMesh->GetId(); - cle += 10000000 * ordType; // sort map by ordType then index + int cle = dependsOnMapKey( aSubMesh ); if ( _mapDepend.find( cle ) == _mapDepend.end()) { _mapDepend[cle] = aSubMesh; @@ -502,19 +578,28 @@ void SMESH_subMesh::insertDependence(const TopoDS_Shape aSubShape) } } +//================================================================================ +/*! + * \brief Return \c true if \a this sub-mesh depends on \a other + */ +//================================================================================ + +bool SMESH_subMesh::DependsOn( const SMESH_subMesh* other ) const +{ + return other ? _mapDepend.count( dependsOnMapKey( other )) : false; +} + //============================================================================= /*! - * + * Return a shape of \a this sub-mesh */ //============================================================================= const TopoDS_Shape & SMESH_subMesh::GetSubShape() const { - //MESSAGE("SMESH_subMesh::GetSubShape"); - return _subShape; + return _subShape; } - //======================================================================= //function : CanAddHypothesis //purpose : return true if theHypothesis can be attached to me: @@ -590,10 +675,6 @@ bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis, SMESH_Hypothesis::Hypothesis_Status SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp) { - // MESSAGE("SMESH_subMesh::AlgoStateEngine"); - //SCRUTE(_algoState); - //SCRUTE(event); - // **** 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 @@ -601,8 +682,8 @@ SMESH_Hypothesis::Hypothesis_Status SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK; SMESHDS_Mesh* meshDS =_father->GetMeshDS(); - //SMESH_Gen* gen =_father->GetGen(); SMESH_Algo* algo = 0; + _algo = 0; if (_subShape.ShapeType() == TopAbs_VERTEX ) { @@ -631,7 +712,7 @@ SMESH_Hypothesis::Hypothesis_Status int oldAlgoState = _algoState; bool modifiedHyp = (event == MODIF_HYP); // if set to true, force event MODIF_ALGO_STATE - bool needFullClean = false; + SMESH_Algo* algoRequiringCleaning = 0; bool isApplicableHyp = IsApplicableHypotesis( anHyp ); @@ -654,8 +735,9 @@ SMESH_Hypothesis::Hypothesis_Status 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( _subShape, filter, true )) - needFullClean = ( !curAlgo->NeedDiscreteBoundary() ); + if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis(_subShape, filter, true )) + if ( !curAlgo->NeedDiscreteBoundary() ) + algoRequiringCleaning = curAlgo; } } @@ -686,12 +768,7 @@ SMESH_Hypothesis::Hypothesis_Status { algo = dynamic_cast (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; - } + algoRequiringCleaning = algo; } } @@ -973,8 +1050,7 @@ SMESH_Hypothesis::Hypothesis_Status // CLEAN was not called at event REMOVE_ALGO because the algo is not applicable to SOLID. algo = dynamic_cast (anHyp); if (!algo->NeedDiscreteBoundary()) - needFullClean = true; - + algoRequiringCleaning = algo; algo = GetAlgo(); if (algo == NULL) // no more applying algo on father { @@ -1038,6 +1114,9 @@ SMESH_Hypothesis::Hypothesis_Status 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 @@ -1050,16 +1129,18 @@ SMESH_Hypothesis::Hypothesis_Status } } - if ( needFullClean ) { + if ( algoRequiringCleaning ) { // added or removed algo is all-dimensional ComputeStateEngine( CLEAN ); - cleanDependsOn(); + cleanDependsOn( algoRequiringCleaning ); ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE ); } if (stateChange || modifiedHyp) ComputeStateEngine(MODIF_ALGO_STATE); + _realComputeCost = ( _algoState == HYP_OK ) ? computeCost() : 0; + return ret; } @@ -1122,7 +1203,7 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo) */ //============================================================================= -void SMESH_subMesh::setAlgoState(int state) +void SMESH_subMesh::setAlgoState(algo_state state) { _algoState = state; } @@ -1152,17 +1233,81 @@ SMESH_Hypothesis::Hypothesis_Status return ret; } -//============================================================================= +//================================================================================ /*! - * + * \brief Remove elements from sub-meshes. + * \param algoRequiringCleaning - an all-dimensional algorithm whose presence + * causes the cleaning. */ -//============================================================================= +//================================================================================ -void SMESH_subMesh::cleanDependsOn() +void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ ) { - SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); - while ( smIt->more() ) - smIt->next()->ComputeStateEngine(CLEAN); + SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false, + /*complexShapeFirst=*/true); + 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 if ( algoRequiringCleaning && algoRequiringCleaning->SupportSubmeshes() ) + { + SMESHDS_Mesh* meshDS = _father->GetMeshDS(); + + // find sub-meshes to keep elements on + set< SMESH_subMesh* > smToKeep; + TopAbs_ShapeEnum prevShapeType = TopAbs_SHAPE; + bool toKeepPrevShapeType = false; + while ( smIt->more() ) + { + SMESH_subMesh* sm = smIt->next(); + sm->ComputeStateEngine(CHECK_COMPUTE_STATE); + if ( !sm->IsEmpty() ) + { + 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& hyps = meshDS->GetHypothesis( sm->_subShape ); + list::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 + SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true); + while ( smIt->more() ) + { + SMESH_subMesh* sm = smIt->next(); + if ( !smToKeep.count( sm )) + sm->ComputeStateEngine(CLEAN); + } + } } //============================================================================= @@ -1173,8 +1318,7 @@ void SMESH_subMesh::cleanDependsOn() void SMESH_subMesh::DumpAlgoState(bool isMain) { - int dim = SMESH_Gen::GetShapeDim(_subShape); -// if (dim < 1) return; + // if (dim < 1) return; if (isMain) { const map < int, SMESH_subMesh * >&subMeshes = DependsOn(); @@ -1186,8 +1330,9 @@ void SMESH_subMesh::DumpAlgoState(bool isMain) sm->DumpAlgoState(false); } } - int type = _subShape.ShapeType(); - MESSAGE("dim = " << dim << " type of shape " << type); + //int type = _subShape.ShapeType(); + MESSAGE("dim = " << SMESH_Gen::GetShapeDim(_subShape) << + " type of shape " << _subShape.ShapeType()); switch (_algoState) { case NO_ALGO: @@ -1234,7 +1379,7 @@ static void cleanSubMesh( SMESH_subMesh * subMesh ) const SMDS_MeshElement * elt = ite->next(); //MESSAGE( " RM elt: "<GetID()<<" ( "<NbNodes()<<" )" ); //meshDS->RemoveElement(elt); - meshDS->RemoveFreeElement(elt, subMeshDS); + meshDS->RemoveFreeElement(elt, 0); } SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes(); @@ -1242,10 +1387,11 @@ static void cleanSubMesh( SMESH_subMesh * subMesh ) const SMDS_MeshNode * node = itn->next(); //MESSAGE( " RM node: "<GetID()); if ( node->NbInverseElements() == 0 ) - meshDS->RemoveFreeNode(node, subMeshDS); + meshDS->RemoveFreeNode(node, 0); else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another meshDS->RemoveNode(node); } + subMeshDS->Clear(); } } } @@ -1258,17 +1404,30 @@ static void cleanSubMesh( SMESH_subMesh * subMesh ) bool SMESH_subMesh::ComputeStateEngine(int event) { - _computeError.reset(); + 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:; + } - //MESSAGE("SMESH_subMesh::ComputeStateEngine"); - //SCRUTE(_computeState); - //SCRUTE(event); + 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 ); @@ -1276,7 +1435,9 @@ bool SMESH_subMesh::ComputeStateEngine(int event) 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()) ) { @@ -1305,16 +1466,15 @@ bool SMESH_subMesh::ComputeStateEngine(int event) case MODIF_ALGO_STATE: algo = GetAlgo(); if (algo && !algo->NeedDiscreteBoundary()) - cleanDependsOn(); // 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(); @@ -1351,12 +1511,13 @@ bool SMESH_subMesh::ComputeStateEngine(int event) if (algo) { if (!algo->NeedDiscreteBoundary()) - cleanDependsOn(); // 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); @@ -1369,27 +1530,38 @@ bool SMESH_subMesh::ComputeStateEngine(int event) break; } TopoDS_Shape shape = _subShape; + algo->SubMeshesToCompute().assign( 1, this ); // check submeshes needed if (_father->HasShapeToMesh() ) { - bool subComputed = false; - if (!algo->OnlyUnaryInput()) - shape = getCollection( gen, algo, subComputed ); - else - subComputed = subMeshesComputed(); + 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() ? true : + algo->SupportSubmeshes() ? !subFailed : ( !subComputed || _father->IsNotConformAllowed() )); - if (!ret) { + if (!ret) + { _computeState = FAILED_TO_COMPUTE; - if ( !algo->NeedDiscreteBoundary() ) + if ( !algo->NeedDiscreteBoundary() && !subFailed ) _computeError = SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH, - "Unexpected computed submesh",algo); - break; + "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(); @@ -1397,10 +1569,10 @@ bool SMESH_subMesh::ComputeStateEngine(int event) _computeState = FAILED_TO_COMPUTE; _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo); try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif + algo->InitComputeError(); + MemoryReserve aMemoryReserve; SMDS_Mesh::CheckMemory(); Kernel_Utils::Localizer loc; @@ -1415,8 +1587,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) { ret = algo->Compute((*_father), shape); } - if ( !_computeError || ( !ret && _computeError->IsOK() ) ) // algo can set _computeError of submesh - _computeError = algo->GetComputeError(); + // algo can set _computeError of submesh + _computeError = SMESH_ComputeError::Worst( _computeError, algo->GetComputeError() ); } catch ( ::SMESH_ComputeError& comperr ) { cout << " SMESH_ComputeError caught" << endl; @@ -1451,9 +1623,12 @@ bool SMESH_subMesh::ComputeStateEngine(int event) } } 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(); + _computeError->myComment = S_ex.what() + skipSalomeShift; } catch ( std::exception& exc ) { if ( !_computeError ) _computeError = SMESH_ComputeError::New(); @@ -1466,14 +1641,21 @@ bool SMESH_subMesh::ComputeStateEngine(int event) 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()) - ret = _father->GetSubMesh( subS.Current() )->IsMeshComputed(); + if ( !_father->GetSubMesh( subS.Current() )->IsMeshComputed() && + ( _subShape.ShapeType() != TopAbs_EDGE || + !algo->isDegenerated( TopoDS::Edge( subS.Current() )))) + ret = false; } // Set _computeError if (!ret && !isComputeErrorSet) @@ -1496,13 +1678,30 @@ bool SMESH_subMesh::ComputeStateEngine(int event) { _computeError.reset(); } - updateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED + + // 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; -#ifdef WITH_SMESH_CANCEL_COMPUTE case COMPUTE_CANCELED: // nothing to do break; -#endif case CLEAN: cleanDependants(); removeSubMeshElementsAndNodes(); @@ -1552,14 +1751,12 @@ bool SMESH_subMesh::ComputeStateEngine(int event) ComputeStateEngine( CLEAN ); algo = GetAlgo(); if (algo && !algo->NeedDiscreteBoundary()) - cleanDependsOn(); // 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(); @@ -1607,13 +1804,14 @@ bool SMESH_subMesh::ComputeStateEngine(int event) ComputeStateEngine( CLEAN ); algo = GetAlgo(); if (algo && !algo->NeedDiscreteBoundary()) - cleanDependsOn(); // 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: { @@ -1772,7 +1970,7 @@ bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, if ( _computeState != COMPUTE_OK ) { if ( _subShape.ShapeType() == TopAbs_EDGE && - BRep_Tool::Degenerated( TopoDS::Edge( _subShape )) ) + SMESH_Algo::isDegenerated( TopoDS::Edge( _subShape )) ) _computeState = COMPUTE_OK; else if ( theComputeOK ) _computeError = SMESH_ComputeError::New(COMPERR_NO_MESH_ON_SHAPE,"",theAlgo); @@ -1839,9 +2037,7 @@ void SMESH_subMesh::updateDependantsState(const compute_event theEvent) for (; it.More(); it.Next()) { const TopoDS_Shape& ancestor = it.Value(); - SMESH_subMesh *aSubMesh = - _father->GetSubMeshContaining(ancestor); - if (aSubMesh) + if ( SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor)) aSubMesh->ComputeStateEngine( theEvent ); } } @@ -1908,9 +2104,11 @@ void SMESH_subMesh::removeSubMeshElementsAndNodes() TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo, - bool & theSubComputed) + bool & theSubComputed, + bool & theSubFailed, + std::vector& theSubs) { - theSubComputed = subMeshesComputed(); + theSubComputed = SubMeshesComputed( & theSubFailed ); TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh(); @@ -1922,17 +2120,20 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy // put in a compound all shapes with the same hypothesis assigned - // and a good ComputState + // and a good ComputeState TopoDS_Compound aCompound; BRep_Builder aBuilder; aBuilder.MakeCompound( aCompound ); + theSubs.clear(); + TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() ); for ( ; anExplorer.More(); anExplorer.Next() ) { const TopoDS_Shape& S = anExplorer.Current(); SMESH_subMesh* subMesh = _father->GetSubMesh( S ); + theSubs.push_back( subMesh ); if ( subMesh == this ) { aBuilder.Add( aCompound, S ); @@ -1943,7 +2144,7 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, if (strcmp( anAlgo->GetName(), theAlgo->GetName()) == 0 && // same algo anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) // same hyps aBuilder.Add( aCompound, S ); - if ( !subMesh->subMeshesComputed() ) + if ( !subMesh->SubMeshesComputed() ) theSubComputed = false; } } @@ -2066,7 +2267,8 @@ void SMESH_subMesh::SetEventListener(EventListener* listener, */ //================================================================================ -void SMESH_subMesh::setEventListener(EventListener* listener, EventListenerData* data) +void SMESH_subMesh::setEventListener(EventListener* listener, + EventListenerData* data) { map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.find( listener ); @@ -2076,8 +2278,21 @@ void SMESH_subMesh::setEventListener(EventListener* listener, EventListenerData* delete curData; l_d->second = data; } - else + else + { + for ( l_d = _eventListeners.begin(); l_d != _eventListeners.end(); ++l_d ) + if ( listener->GetName() == l_d->first->GetName() ) + { + EventListenerData* curData = l_d->second; + if ( curData && curData != data && curData->IsDeletable() ) + delete curData; + if ( l_d->first != listener && l_d->first->IsDeletable() ) + delete l_d->first; + _eventListeners.erase( l_d ); + break; + } _eventListeners.insert( make_pair( listener, data )); + } } //================================================================================ @@ -2127,17 +2342,22 @@ void SMESH_subMesh::notifyListenersOnEvent( const int event, const event_type eventType, SMESH_Hypothesis* hyp) { - map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.begin(); - for ( ; l_d != _eventListeners.end(); ++l_d ) + 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 bool isDeletable = li_da.first->IsDeletable(); + li_da.first->ProcessEvent( event, eventType, this, li_da.second, hyp ); - li_da.first->myBusySM.erase( this ); + + if ( !isDeletable || _eventListeners.count( li_da.first )) + li_da.first->myBusySM.erase( this ); // a listener is hopefully not dead } } } @@ -2153,16 +2373,18 @@ void SMESH_subMesh::DeleteEventListener(EventListener* listener) { map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.find( listener ); - if ( l_d != _eventListeners.end() ) { - if ( l_d->first && l_d->first->IsDeletable() ) - { - l_d->first->BeforeDelete( this, l_d->second ); - delete l_d->first; - } + if ( l_d != _eventListeners.end() && l_d->first ) + { if ( l_d->second && l_d->second->IsDeletable() ) { delete l_d->second; } + l_d->first->myBusySM.erase( this ); + if ( l_d->first->IsDeletable() ) + { + l_d->first->BeforeDelete( this, l_d->second ); + delete l_d->first; + } _eventListeners.erase( l_d ); } } @@ -2244,6 +2466,7 @@ void SMESH_subMeshEventListener::ProcessEvent(const int event, (*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 ); @@ -2301,22 +2524,23 @@ namespace { //================================================================================ SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeSelf, - const bool reverse) + const bool reverse) const { + SMESH_subMesh *me = (SMESH_subMesh*) this; SMESH_subMesh *prepend=0, *append=0; if ( includeSelf ) { - if ( reverse ) prepend = this; - else append = this; + if ( reverse ) prepend = me; + else append = me; } typedef map < int, SMESH_subMesh * > TMap; if ( reverse ) { return SMESH_subMeshIteratorPtr - ( new _Iterator( new SMDS_mapReverseIterator( DependsOn() ), prepend, append )); + ( new _Iterator( new SMDS_mapReverseIterator( me->DependsOn() ), prepend, append )); } { return SMESH_subMeshIteratorPtr - ( new _Iterator( new SMDS_mapIterator( DependsOn() ), prepend, append )); + ( new _Iterator( new SMDS_mapIterator( me->DependsOn() ), prepend, append )); } }