X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_subMesh.cxx;h=08b033dc97ce9a590424fa23674be157dae46844;hp=e3ad2236aae1e31a68607570b8e2967395fa4bbe;hb=refs%2Ftags%2FdistribGeom_06Mar13;hpb=c4bd4ff43b510056ee6a6b0ffdf8693c4adb1be5 diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index e3ad2236a..08b033dc9 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -1,30 +1,30 @@ -// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2012 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 +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // -// 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. +// 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. // -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // SMESH SMESH : implementaion of SMESH idl descriptions // File : SMESH_subMesh.cxx // Author : Paul RASCLE, EDF // Module : SMESH -// + #include "SMESH_subMesh.hxx" #include "SMESH_Algo.hxx" @@ -38,6 +38,8 @@ #include "SMDS_SetIterator.hxx" #include "SMDSAbs_ElementType.hxx" +#include + #include "utilities.h" #include "OpUtil.hxx" #include "Basics_Utils.hxx" @@ -86,22 +88,22 @@ 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; + } } //============================================================================= @@ -114,7 +116,7 @@ SMESH_subMesh::~SMESH_subMesh() { MESSAGE("SMESH_subMesh::~SMESH_subMesh"); // **** - DeleteOwnListeners(); + deleteOwnListeners(); } //============================================================================= @@ -147,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() ) { @@ -175,7 +188,20 @@ SMESH_subMesh *SMESH_subMesh::GetFirstToCompute() //================================================================================ /*! - * \brief Allow algo->Compute() if a subshape of lower dim is meshed but + * \brief Returns a current algorithm + */ +//================================================================================ + +SMESH_Algo* SMESH_subMesh::GetAlgo() const +{ + if ( !_algo ) + ((SMESH_subMesh*)this)->_algo = _father->GetGen()->GetAlgo(*_father, _subShape); + return _algo; +} + +//================================================================================ +/*! + * \brief Allow algo->Compute() if a sub-shape of lower dim is meshed but * none mesh entity is bound to it (PAL13615, 2nd part) */ //================================================================================ @@ -240,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() ) @@ -257,66 +284,72 @@ 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; @@ -328,23 +361,23 @@ bool SMESH_subMesh::SubMeshesComputed() */ //============================================================================= -bool SMESH_subMesh::SubMeshesReady() -{ - bool subMeshesReady = true; - SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true); - while ( smIt->more() ) { - SMESH_subMesh *sm = smIt->next(); - bool computeOk = (sm->GetComputeState() == COMPUTE_OK || - sm->GetComputeState() == READY_TO_COMPUTE); - if (!computeOk) - { - subMeshesReady = false; - SCRUTE(sm->GetId()); - break; - } - } - return subMeshesReady; -} +// bool SMESH_subMesh::SubMeshesReady() +// { +// bool subMeshesReady = true; +// SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true); +// while ( smIt->more() ) { +// SMESH_subMesh *sm = smIt->next(); +// bool computeOk = (sm->GetComputeState() == COMPUTE_OK || +// sm->GetComputeState() == READY_TO_COMPUTE); +// if (!computeOk) +// { +// subMeshesReady = false; +// SCRUTE(sm->GetId()); +// break; +// } +// } +// return subMeshesReady; +// } //============================================================================= /*! @@ -374,24 +407,28 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() //MESSAGE("compound"); for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();exp.Next()) { - InsertDependence(exp.Current()); + insertDependence(exp.Current()); } for (TopExp_Explorer exp(_subShape, TopAbs_SHELL, TopAbs_SOLID); exp.More(); exp.Next()) { if ( BRep_Tool::IsClosed(exp.Current() )) - InsertDependence(exp.Current()); //only shell not in solid + insertDependence(exp.Current()); //only shell not in solid else for (TopExp_Explorer expF(exp.Current(), TopAbs_FACE); expF.More();expF.Next()) - InsertDependence(expF.Current()); // issue 0020959: HEXA_3D fails on shell + insertDependence(expF.Current()); // issue 0020959: HEXA_3D fails on shell } for (TopExp_Explorer exp(_subShape, TopAbs_FACE, TopAbs_SHELL); exp.More();exp.Next()) { - InsertDependence(exp.Current()); + insertDependence(exp.Current()); } for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();exp.Next()) { - InsertDependence(exp.Current()); + insertDependence(exp.Current()); + } + for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX, TopAbs_EDGE); exp.More();exp.Next()) + { + insertDependence(exp.Current()); } break; } @@ -400,7 +437,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() //MESSAGE("compsolid"); for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More(); exp.Next()) { - InsertDependence(exp.Current()); + insertDependence(exp.Current()); } break; } @@ -409,7 +446,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() //MESSAGE("shell"); for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More(); exp.Next()) { - InsertDependence(exp.Current()); + insertDependence(exp.Current()); } break; } @@ -418,7 +455,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() //MESSAGE("wire"); for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More(); exp.Next()) { - InsertDependence(exp.Current()); + insertDependence(exp.Current()); } break; } @@ -428,7 +465,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() if(_father->HasShapeToMesh()) { for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();exp.Next()) { - InsertDependence(exp.Current()); + insertDependence(exp.Current()); } } break; @@ -438,7 +475,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() //MESSAGE("face"); for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();exp.Next()) { - InsertDependence(exp.Current()); + insertDependence(exp.Current()); } break; } @@ -447,7 +484,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() //MESSAGE("edge"); for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More(); exp.Next()) { - InsertDependence(exp.Current()); + insertDependence(exp.Current()); } break; } @@ -470,9 +507,8 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() */ //============================================================================= -void SMESH_subMesh::InsertDependence(const TopoDS_Shape aSubShape) +void SMESH_subMesh::insertDependence(const TopoDS_Shape aSubShape) { - //MESSAGE("SMESH_subMesh::InsertDependence"); SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape); int type = aSubShape.ShapeType(); int ordType = 9 - type; // 2 = Vertex, 8 = CompSolid @@ -509,12 +545,13 @@ bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) cons { int aHypDim = theHypothesis->GetDim(); int aShapeDim = SMESH_Gen::GetShapeDim(_subShape); - if (aHypDim == 3 && aShapeDim == 3) { - // check case of open shell - //if (_subShape.ShapeType() == TopAbs_SHELL && !_subShape.Closed()) - if (_subShape.ShapeType() == TopAbs_SHELL && !BRep_Tool::IsClosed(_subShape)) - return false; - } + // issue 21106. Forbid 3D mesh on the SHELL + // if (aHypDim == 3 && aShapeDim == 3) { + // // check case of open shell + // //if (_subShape.ShapeType() == TopAbs_SHELL && !_subShape.Closed()) + // if (_subShape.ShapeType() == TopAbs_SHELL && !BRep_Tool::IsClosed(_subShape)) + // return false; + // } if ( aHypDim <= aShapeDim ) return true; @@ -530,8 +567,14 @@ bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis, const TopAbs_ShapeEnum theShapeType) { if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO) + { // algorithm - return ( theHypothesis->GetShapeType() & (1<< theShapeType)); + if ( theHypothesis->GetShapeType() & (1<< theShapeType)) + // issue 21106. Forbid 3D mesh on the SHELL + return !( theHypothesis->GetDim() == 3 && theShapeType == TopAbs_SHELL ); + else + return false; + } // hypothesis switch ( theShapeType ) { @@ -567,10 +610,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 @@ -578,8 +617,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 ) { @@ -595,7 +634,7 @@ SMESH_Hypothesis::Hypothesis_Status if ( event != REMOVE_FATHER_ALGO ) { _algoState = NO_ALGO; - algo = gen->GetAlgo(*_father, _subShape); + algo = GetAlgo(); if ( algo ) { _algoState = MISSING_HYP; if ( event == REMOVE_FATHER_HYP || @@ -608,7 +647,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 ); @@ -631,8 +670,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->NeedDescretBoundary() ); + if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis(_subShape, filter, true )) + if ( !curAlgo->NeedDiscreteBoundary() ) + algoRequiringCleaning = curAlgo; } } @@ -644,7 +684,7 @@ SMESH_Hypothesis::Hypothesis_Status if ( ! CanAddHypothesis( anHyp )) // check dimension return SMESH_Hypothesis::HYP_BAD_DIM; - if ( /*!anHyp->IsAuxiliary() &&*/ GetSimilarAttached( _subShape, anHyp ) ) + if ( /*!anHyp->IsAuxiliary() &&*/ getSimilarAttached( _subShape, anHyp ) ) return SMESH_Hypothesis::HYP_ALREADY_EXIST; if ( !meshDS->AddHypothesis(_subShape, anHyp)) @@ -662,13 +702,8 @@ SMESH_Hypothesis::Hypothesis_Status if (event == REMOVE_ALGO) { algo = dynamic_cast (anHyp); - if (!algo->NeedDescretBoundary()) - { - // 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; - } + if (!algo->NeedDiscreteBoundary()) + algoRequiringCleaning = algo; } } @@ -688,16 +723,16 @@ SMESH_Hypothesis::Hypothesis_Status case ADD_HYP: break; case ADD_ALGO: { - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); ASSERT(algo); if (algo->CheckHypothesis((*_father),_subShape, aux_ret)) - SetAlgoState(HYP_OK); + setAlgoState(HYP_OK); else if ( algo->IsStatusFatal( aux_ret )) { meshDS->RemoveHypothesis(_subShape, anHyp); ret = aux_ret; } else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); break; } case REMOVE_HYP: @@ -705,26 +740,26 @@ SMESH_Hypothesis::Hypothesis_Status case ADD_FATHER_HYP: break; case ADD_FATHER_ALGO: { // Algo just added in father - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); ASSERT(algo); if ( algo == anHyp ) { if ( algo->CheckHypothesis((*_father),_subShape, aux_ret)) - SetAlgoState(HYP_OK); + setAlgoState(HYP_OK); else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); } break; } case REMOVE_FATHER_HYP: break; case REMOVE_FATHER_ALGO: { - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); if (algo) { if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) - SetAlgoState(HYP_OK); + setAlgoState(HYP_OK); else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); } break; } @@ -741,10 +776,10 @@ SMESH_Hypothesis::Hypothesis_Status switch (event) { case ADD_HYP: { - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); ASSERT(algo); if ( algo->CheckHypothesis((*_father),_subShape, ret )) - SetAlgoState(HYP_OK); + setAlgoState(HYP_OK); if (SMESH_Hypothesis::IsStatusFatal( ret )) meshDS->RemoveHypothesis(_subShape, anHyp); else if (!_father->IsUsedHypothesis( anHyp, this )) @@ -755,70 +790,70 @@ SMESH_Hypothesis::Hypothesis_Status break; } case ADD_ALGO: { //already existing algo : on father ? - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); ASSERT(algo); if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status - SetAlgoState(HYP_OK); + setAlgoState(HYP_OK); else if ( algo->IsStatusFatal( aux_ret )) { meshDS->RemoveHypothesis(_subShape, anHyp); ret = aux_ret; } else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); break; } case REMOVE_HYP: break; case REMOVE_ALGO: { // perhaps a father algo applies ? - algo = gen->GetAlgo((*_father), _subShape); - if (algo == NULL) // no more algo applying on subShape... + algo = GetAlgo(); + if (algo == NULL) // no more algo applying on sub-shape... { - SetAlgoState(NO_ALGO); + setAlgoState(NO_ALGO); } else { if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) - SetAlgoState(HYP_OK); + setAlgoState(HYP_OK); else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); } break; } case MODIF_HYP: // assigned hypothesis value may become good case ADD_FATHER_HYP: { - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); ASSERT(algo); if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) - SetAlgoState(HYP_OK); + setAlgoState(HYP_OK); else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); break; } case ADD_FATHER_ALGO: { // new father algo - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); ASSERT( algo ); if ( algo == anHyp ) { if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) - SetAlgoState(HYP_OK); + setAlgoState(HYP_OK); else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); } break; } case REMOVE_FATHER_HYP: // nothing to do break; case REMOVE_FATHER_ALGO: { - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); if (algo == NULL) // no more applying algo on father { - SetAlgoState(NO_ALGO); + setAlgoState(NO_ALGO); } else { if ( algo->CheckHypothesis((*_father),_subShape , aux_ret )) - SetAlgoState(HYP_OK); + setAlgoState(HYP_OK); else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); } break; } @@ -834,7 +869,7 @@ SMESH_Hypothesis::Hypothesis_Status switch (event) { case ADD_HYP: { - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); ASSERT(algo); if (!algo->CheckHypothesis((*_father),_subShape, ret )) { @@ -857,7 +892,7 @@ SMESH_Hypothesis::Hypothesis_Status break; } case ADD_ALGO: { //already existing algo : on father ? - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) { // check if algo changes SMESH_HypoFilter f; @@ -870,24 +905,24 @@ SMESH_Hypothesis::Hypothesis_Status modifiedHyp = true; } else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); break; } case REMOVE_HYP: { - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); ASSERT(algo); if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) - SetAlgoState(HYP_OK); + setAlgoState(HYP_OK); else - SetAlgoState(MISSING_HYP); + 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... + algo = GetAlgo(); + if (algo == NULL) // no more algo applying on sub-shape... { - SetAlgoState(NO_ALGO); + setAlgoState(NO_ALGO); } else { @@ -897,13 +932,13 @@ SMESH_Hypothesis::Hypothesis_Status modifiedHyp = true; } else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); } break; } case MODIF_HYP: // hypothesis value may become bad case ADD_FATHER_HYP: { // new father hypothesis ? - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); ASSERT(algo); if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) { @@ -911,11 +946,11 @@ SMESH_Hypothesis::Hypothesis_Status modifiedHyp = true; } else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); break; } case ADD_FATHER_ALGO: { - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); if ( algo == anHyp ) { // a new algo on father if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) { // check if algo changes @@ -929,33 +964,32 @@ SMESH_Hypothesis::Hypothesis_Status modifiedHyp = true; } else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); } break; } case REMOVE_FATHER_HYP: { - algo = gen->GetAlgo((*_father), _subShape); + 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 ) ) + if ( !getSimilarAttached( _subShape, anHyp ) ) modifiedHyp = true; } else - SetAlgoState(MISSING_HYP); + 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 (anHyp); - if (!algo->NeedDescretBoundary()) - needFullClean = true; - - algo = gen->GetAlgo((*_father), _subShape); + if (!algo->NeedDiscreteBoundary()) + algoRequiringCleaning = algo; + algo = GetAlgo(); if (algo == NULL) // no more applying algo on father { - SetAlgoState(NO_ALGO); + setAlgoState(NO_ALGO); } else { @@ -965,7 +999,7 @@ SMESH_Hypothesis::Hypothesis_Status modifiedHyp = true; } else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); } break; } @@ -993,12 +1027,12 @@ SMESH_Hypothesis::Hypothesis_Status 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()) + if ( !upperAlgo->NeedDiscreteBoundary() && !upperAlgo->SupportSubmeshes()) ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO; } // is algo hiding? if ( ret == SMESH_Hypothesis::HYP_OK && - !algo->NeedDescretBoundary() && + !algo->NeedDiscreteBoundary() && !algo->SupportSubmeshes()) { TopoDS_Shape algoAssignedTo, otherAssignedTo; gen->GetAlgo( *_father, _subShape, &algoAssignedTo ); @@ -1015,10 +1049,10 @@ SMESH_Hypothesis::Hypothesis_Status if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK algo->SetEventListener( this ); - NotifyListenersOnEvent( event, ALGO_EVENT, anHyp ); + notifyListenersOnEvent( event, ALGO_EVENT, anHyp ); if ( stateChange && oldAlgoState == HYP_OK ) { // hyp becomes KO - DeleteOwnListeners(); + deleteOwnListeners(); SetIsAlwaysComputed( false ); if (_subShape.ShapeType() == TopAbs_VERTEX ) { // restore default states @@ -1027,10 +1061,10 @@ SMESH_Hypothesis::Hypothesis_Status } } - if ( needFullClean ) { + if ( algoRequiringCleaning ) { // added or removed algo is all-dimensional ComputeStateEngine( CLEAN ); - CleanDependsOn(); + cleanDependsOn( algoRequiringCleaning ); ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE ); } @@ -1053,9 +1087,9 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo) // 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 + // check only algo that doesn't NeedDiscreteBoundary(): because mesh made // on a sub-shape will be ignored by theAlgo - if ( theAlgo->NeedDescretBoundary() || + if ( theAlgo->NeedDiscreteBoundary() || !theAlgo->OnlyUnaryInput() ) // all adjacent shapes will be meshed by this algo? return true; @@ -1084,7 +1118,7 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo) // check algo attached to smAdjacent SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent); if (algo && - !algo->NeedDescretBoundary() && + !algo->NeedDiscreteBoundary() && algo->OnlyUnaryInput()) return false; // NOT CONFORM MESH WILL BE PRODUCED } @@ -1099,7 +1133,7 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo) */ //============================================================================= -void SMESH_subMesh::SetAlgoState(int state) +void SMESH_subMesh::setAlgoState(algo_state state) { _algoState = state; } @@ -1129,17 +1163,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); + } + } } //============================================================================= @@ -1235,11 +1333,19 @@ static void cleanSubMesh( SMESH_subMesh * subMesh ) bool SMESH_subMesh::ComputeStateEngine(int event) { - _computeError.reset(); - - //MESSAGE("SMESH_subMesh::ComputeStateEngine"); - //SCRUTE(_computeState); - //SCRUTE(event); + switch ( event ) { + case MODIF_ALGO_STATE: + case COMPUTE: + //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 (_subShape.ShapeType() == TopAbs_VERTEX) { @@ -1247,7 +1353,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event) SMESHDS_SubMesh* smDS = GetSubMeshDS(); if ( smDS && smDS->NbNodes() ) { if ( event == CLEAN ) { - CleanDependants(); + cleanDependants(); cleanSubMesh( this ); } else @@ -1262,7 +1368,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event) } } if ( event == MODIF_ALGO_STATE ) - CleanDependants(); + cleanDependants(); return true; } SMESH_Gen *gen = _father->GetGen(); @@ -1280,9 +1386,9 @@ bool SMESH_subMesh::ComputeStateEngine(int event) switch (event) { case MODIF_ALGO_STATE: - algo = gen->GetAlgo((*_father), _subShape); - if (algo && !algo->NeedDescretBoundary()) - CleanDependsOn(); // clean sub-meshes with event CLEAN + algo = GetAlgo(); + if (algo && !algo->NeedDiscreteBoundary()) + cleanDependsOn( algo ); // clean sub-meshes with event CLEAN if ( _algoState == HYP_OK ) _computeState = READY_TO_COMPUTE; break; @@ -1293,8 +1399,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) break; #endif case CLEAN: - CleanDependants(); - RemoveSubMeshElementsAndNodes(); + cleanDependants(); + removeSubMeshElementsAndNodes(); break; case SUBMESH_COMPUTED: // nothing to do break; @@ -1303,6 +1409,10 @@ bool SMESH_subMesh::ComputeStateEngine(int event) break; case MESH_ENTITY_REMOVED: break; + case SUBMESH_LOADED: + loadDependentMeshes(); + ComputeSubMeshStateEngine( SUBMESH_LOADED ); + //break; case CHECK_COMPUTE_STATE: if ( IsMeshComputed() ) _computeState = COMPUTE_OK; @@ -1320,55 +1430,58 @@ bool SMESH_subMesh::ComputeStateEngine(int event) { case MODIF_ALGO_STATE: _computeState = NOT_READY; - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); if (algo) { - if (!algo->NeedDescretBoundary()) - CleanDependsOn(); // clean sub-meshes with event CLEAN + if (!algo->NeedDiscreteBoundary()) + cleanDependsOn( algo ); // clean sub-meshes with event CLEAN if ( _algoState == HYP_OK ) _computeState = READY_TO_COMPUTE; } break; case COMPUTE: { - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); ASSERT(algo); ret = algo->CheckHypothesis((*_father), _subShape, hyp_status); if (!ret) { MESSAGE("***** verify compute state *****"); _computeState = NOT_READY; - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); break; } TopoDS_Shape shape = _subShape; // check submeshes needed if (_father->HasShapeToMesh() ) { - bool subComputed = false; + bool subComputed = false, subFailed = false; if (!algo->OnlyUnaryInput()) - shape = GetCollection( gen, algo, subComputed ); + shape = getCollection( gen, algo, subComputed, subFailed ); else subComputed = SubMeshesComputed(); - ret = ( algo->NeedDescretBoundary() ? subComputed : - algo->SupportSubmeshes() ? true : + ret = ( algo->NeedDiscreteBoundary() ? subComputed : + algo->SupportSubmeshes() ? !subFailed : ( !subComputed || _father->IsNotConformAllowed() )); - if (!ret) { + if (!ret) + { _computeState = FAILED_TO_COMPUTE; - if ( !algo->NeedDescretBoundary() ) + if ( !algo->NeedDiscreteBoundary() && !subFailed ) _computeError = SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH, "Unexpected computed submesh",algo); - break; + break; // goto exit } } - // compute -// CleanDependants(); for "UseExisting_*D" algos -// RemoveSubMeshElementsAndNodes(); + // Compute + + //cleanDependants(); for "UseExisting_*D" algos + //removeSubMeshElementsAndNodes(); + loadDependentMeshes(); ret = false; _computeState = FAILED_TO_COMPUTE; _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo); try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif algo->InitComputeError(); @@ -1389,6 +1502,11 @@ bool SMESH_subMesh::ComputeStateEngine(int event) if ( !_computeError || ( !ret && _computeError->IsOK() ) ) // algo can set _computeError of submesh _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 ) { @@ -1417,9 +1535,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(); @@ -1432,16 +1553,20 @@ bool SMESH_subMesh::ComputeStateEngine(int event) else ret = false; } + // 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) // check if anything was built + if (ret) { for (; ret && subS.More(); subS.Next()) ret = _father->GetSubMesh( subS.Current() )->IsMeshComputed(); } - bool isComputeErrorSet = !CheckComputeError( algo, shape ); + // Set _computeError if (!ret && !isComputeErrorSet) { - // Set _computeError for (subS.ReInit(); subS.More(); subS.Next()) { SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() ); @@ -1456,11 +1581,30 @@ bool SMESH_subMesh::ComputeStateEngine(int event) } } } - if (ret) + if (ret && _computeError && _computeError->myName != COMPERR_WARNING ) { _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 @@ -1468,17 +1612,17 @@ bool SMESH_subMesh::ComputeStateEngine(int event) break; #endif case CLEAN: - CleanDependants(); - RemoveSubMeshElementsAndNodes(); + cleanDependants(); + removeSubMeshElementsAndNodes(); _computeState = NOT_READY; - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); if (algo) { ret = algo->CheckHypothesis((*_father), _subShape, hyp_status); if (ret) _computeState = READY_TO_COMPUTE; else - SetAlgoState(MISSING_HYP); + setAlgoState(MISSING_HYP); } break; case SUBMESH_COMPUTED: // nothing to do @@ -1488,11 +1632,15 @@ bool SMESH_subMesh::ComputeStateEngine(int event) // happen after retrieval from a file ComputeStateEngine( CHECK_COMPUTE_STATE ); ComputeSubMeshStateEngine( SUBMESH_RESTORED ); - algo = gen->GetAlgo(*_father, _subShape); + 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; @@ -1510,9 +1658,9 @@ bool SMESH_subMesh::ComputeStateEngine(int event) { case MODIF_ALGO_STATE: ComputeStateEngine( CLEAN ); - algo = gen->GetAlgo((*_father), _subShape); - if (algo && !algo->NeedDescretBoundary()) - CleanDependsOn(); // clean sub-meshes with event CLEAN + algo = GetAlgo(); + if (algo && !algo->NeedDiscreteBoundary()) + cleanDependsOn( algo ); // clean sub-meshes with event CLEAN break; case COMPUTE: // nothing to do break; @@ -1521,8 +1669,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) break; #endif case CLEAN: - CleanDependants(); // clean sub-meshes, dependant on this one, with event CLEAN - RemoveSubMeshElementsAndNodes(); + cleanDependants(); // clean sub-meshes, dependant on this one, with event CLEAN + removeSubMeshElementsAndNodes(); _computeState = NOT_READY; if ( _algoState == HYP_OK ) _computeState = READY_TO_COMPUTE; @@ -1532,12 +1680,12 @@ bool SMESH_subMesh::ComputeStateEngine(int event) case SUBMESH_RESTORED: ComputeStateEngine( CHECK_COMPUTE_STATE ); ComputeSubMeshStateEngine( SUBMESH_RESTORED ); - algo = gen->GetAlgo(*_father, _subShape); + algo = GetAlgo(); if (algo) algo->SubmeshRestored( this ); break; case MESH_ENTITY_REMOVED: - UpdateDependantsState( CHECK_COMPUTE_STATE ); - ComputeStateEngine( CHECK_COMPUTE_STATE ); + updateDependantsState ( CHECK_COMPUTE_STATE ); + ComputeStateEngine ( CHECK_COMPUTE_STATE ); ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE ); break; case CHECK_COMPUTE_STATE: @@ -1548,6 +1696,9 @@ bool SMESH_subMesh::ComputeStateEngine(int event) _computeState = NOT_READY; } break; + case SUBMESH_LOADED: + // already treated event, thanks to which _computeState == COMPUTE_OK + break; default: ASSERT(0); break; @@ -1562,9 +1713,9 @@ bool SMESH_subMesh::ComputeStateEngine(int event) case MODIF_ALGO_STATE: if ( !IsEmpty() ) ComputeStateEngine( CLEAN ); - algo = gen->GetAlgo((*_father), _subShape); - if (algo && !algo->NeedDescretBoundary()) - CleanDependsOn(); // clean sub-meshes with event CLEAN + algo = GetAlgo(); + if (algo && !algo->NeedDiscreteBoundary()) + cleanDependsOn( algo ); // clean sub-meshes with event CLEAN if (_algoState == HYP_OK) _computeState = READY_TO_COMPUTE; else @@ -1572,17 +1723,15 @@ bool SMESH_subMesh::ComputeStateEngine(int event) break; case COMPUTE: // nothing to do break; -#ifdef WITH_SMESH_CANCEL_COMPUTE case COMPUTE_CANCELED: { - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); algo->CancelCompute(); } break; -#endif case CLEAN: - CleanDependants(); // submeshes dependent on me should be cleaned as well - RemoveSubMeshElementsAndNodes(); + cleanDependants(); // submeshes dependent on me should be cleaned as well + removeSubMeshElementsAndNodes(); break; case SUBMESH_COMPUTED: // allow retry compute if (_algoState == HYP_OK) @@ -1604,6 +1753,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) else _computeState = NOT_READY; break; + // case SUBMESH_LOADED: + // break; default: ASSERT(0); break; @@ -1616,7 +1767,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event) break; } - NotifyListenersOnEvent( event, COMPUTE_EVENT ); + notifyListenersOnEvent( event, COMPUTE_EVENT ); return ret; } @@ -1641,17 +1792,17 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap) return ret; } - SMESH_Gen *gen = _father->GetGen(); + //SMESH_Gen *gen = _father->GetGen(); SMESH_Algo *algo = 0; SMESH_Hypothesis::Hypothesis_Status hyp_status; - algo = gen->GetAlgo((*_father), _subShape); + algo = GetAlgo(); if(algo && !aResMap.count(this) ) { ret = algo->CheckHypothesis((*_father), _subShape, hyp_status); if (!ret) return false; - if (_father->HasShapeToMesh() && algo->NeedDescretBoundary()) + if (_father->HasShapeToMesh() && algo->NeedDiscreteBoundary()) { // check submeshes needed bool subMeshEvaluated = true; @@ -1686,18 +1837,20 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap) */ //======================================================================= -bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& theShape) +bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, + const bool theComputeOK, + const TopoDS_Shape& theShape) { bool noErrors = true; if ( !theShape.IsNull() ) { // Check state of submeshes - if ( !theAlgo->NeedDescretBoundary()) + if ( !theAlgo->NeedDiscreteBoundary()) { SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); while ( smIt->more() ) - if ( !smIt->next()->CheckComputeError( theAlgo )) + if ( !smIt->next()->checkComputeError( theAlgo, theComputeOK )) noErrors = false; } @@ -1709,27 +1862,39 @@ bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t for (TopoDS_Iterator subIt( theShape ); subIt.More(); subIt.Next()) { SMESH_subMesh* sm = _father->GetSubMesh( subIt.Value() ); if ( sm != this ) { - if ( !sm->CheckComputeError( theAlgo, sm->GetSubShape() )) + if ( !sm->checkComputeError( theAlgo, theComputeOK, sm->GetSubShape() )) noErrors = false; - UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED + updateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED } } } } { - // Check my state + + // Set my _computeState + if ( !_computeError || _computeError->IsOK() ) { + // no error description is set to this sub-mesh, check if any mesh is computed _computeState = IsMeshComputed() ? COMPUTE_OK : FAILED_TO_COMPUTE; + if ( _computeState != COMPUTE_OK ) + { + if ( _subShape.ShapeType() == TopAbs_EDGE && + BRep_Tool::Degenerated( TopoDS::Edge( _subShape )) ) + _computeState = COMPUTE_OK; + else if ( theComputeOK ) + _computeError = SMESH_ComputeError::New(COMPERR_NO_MESH_ON_SHAPE,"",theAlgo); + } } - else + + if ( _computeError && !_computeError->IsOK() ) { if ( !_computeError->myAlgo ) _computeError->myAlgo = theAlgo; // Show error SMESH_Comment text; - text << theAlgo->GetName() << " failed on subshape #" << _Id << " with error "; + text << theAlgo->GetName() << " failed on sub-shape #" << _Id << " with error "; if (_computeError->IsCommon() ) text << _computeError->CommonName(); else @@ -1739,7 +1904,8 @@ bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t INFOS( text ); - _computeState = FAILED_TO_COMPUTE; + _computeState = _computeError->IsKO() ? FAILED_TO_COMPUTE : COMPUTE_OK; + noErrors = false; } } @@ -1747,51 +1913,11 @@ bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t } //======================================================================= -//function : ApplyToCollection -//purpose : Apply theAlgo to all subshapes in theCollection -//======================================================================= - -bool SMESH_subMesh::ApplyToCollection (SMESH_Algo* theAlgo, - const TopoDS_Shape& theCollection) -{ - MESSAGE("SMESH_subMesh::ApplyToCollection"); - ASSERT ( !theAlgo->NeedDescretBoundary() ); - - if ( _computeError ) - _computeError->myName = COMPERR_OK; - - bool ok = theAlgo->Compute( *_father, theCollection ); - - // set _computeState of subshapes - TopExp_Explorer anExplorer( theCollection, _subShape.ShapeType() ); - for ( ; anExplorer.More(); anExplorer.Next() ) - { - if ( SMESH_subMesh* subMesh = _father->GetSubMeshContaining( anExplorer.Current() )) - { - bool localOK = subMesh->CheckComputeError( theAlgo ); - if ( !ok && localOK && !subMesh->IsMeshComputed() ) - { - subMesh->_computeError = theAlgo->GetComputeError(); - if ( subMesh->_computeError->IsOK() ) - _computeError = SMESH_ComputeError::New(COMPERR_ALGO_FAILED); - localOK = CheckComputeError( theAlgo ); - } - if ( localOK ) - subMesh->UpdateDependantsState( SUBMESH_COMPUTED ); - subMesh->UpdateSubMeshState( localOK ? COMPUTE_OK : FAILED_TO_COMPUTE ); - } - } - - return true; -} - - -//======================================================================= -//function : UpdateSubMeshState +//function : updateSubMeshState //purpose : //======================================================================= -void SMESH_subMesh::UpdateSubMeshState(const compute_state theState) +void SMESH_subMesh::updateSubMeshState(const compute_state theState) { SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); while ( smIt->more() ) @@ -1803,28 +1929,25 @@ void SMESH_subMesh::UpdateSubMeshState(const compute_state theState) //purpose : //======================================================================= -void SMESH_subMesh::ComputeSubMeshStateEngine(int event) +void SMESH_subMesh::ComputeSubMeshStateEngine(int event, const bool includeSelf) { - SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); + SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(includeSelf,false); while ( smIt->more() ) smIt->next()->ComputeStateEngine(event); } //======================================================================= -//function : UpdateDependantsState +//function : updateDependantsState //purpose : //======================================================================= -void SMESH_subMesh::UpdateDependantsState(const compute_event theEvent) +void SMESH_subMesh::updateDependantsState(const compute_event theEvent) { - //MESSAGE("SMESH_subMesh::UpdateDependantsState"); TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape )); 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 ); } } @@ -1835,7 +1958,7 @@ void SMESH_subMesh::UpdateDependantsState(const compute_event theEvent) */ //============================================================================= -void SMESH_subMesh::CleanDependants() +void SMESH_subMesh::cleanDependants() { int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1; @@ -1848,7 +1971,8 @@ void SMESH_subMesh::CleanDependants() // will erase mesh on other shapes in a compound if ( ancestor.ShapeType() >= TopAbs_SOLID ) { SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor); - if (aSubMesh) + if (aSubMesh && + !aSubMesh->IsEmpty() ) // prevent infinite CLEAN via event lesteners aSubMesh->ComputeStateEngine(CLEAN); } } @@ -1861,10 +1985,8 @@ void SMESH_subMesh::CleanDependants() */ //============================================================================= -void SMESH_subMesh::RemoveSubMeshElementsAndNodes() +void SMESH_subMesh::removeSubMeshElementsAndNodes() { - //SCRUTE(_subShape.ShapeType()); - cleanSubMesh( this ); // algo may bind a submesh not to _subShape, eg 3D algo @@ -1885,18 +2007,17 @@ void SMESH_subMesh::RemoveSubMeshElementsAndNodes() } //======================================================================= -//function : GetCollection +//function : getCollection //purpose : return a shape containing all sub-shapes of the MainShape that can be // meshed at once along with _subShape //======================================================================= -TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, +TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo, - bool & theSubComputed) + bool & theSubComputed, + bool & theSubFailed) { - MESSAGE("SMESH_subMesh::GetCollection"); - - theSubComputed = SubMeshesComputed(); + theSubComputed = SubMeshesComputed( & theSubFailed ); TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh(); @@ -1938,14 +2059,14 @@ TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, } //======================================================================= -//function : GetSimilarAttached +//function : getSimilarAttached //purpose : return a hypothesis attached to theShape. // If theHyp is provided, similar but not same hypotheses // is returned; else only applicable ones having theHypType // is returned //======================================================================= -const SMESH_Hypothesis* SMESH_subMesh::GetSimilarAttached(const TopoDS_Shape& theShape, +const SMESH_Hypothesis* SMESH_subMesh::getSimilarAttached(const TopoDS_Shape& theShape, const SMESH_Hypothesis * theHyp, const int theHypType) { @@ -1978,7 +2099,7 @@ SMESH_Hypothesis::Hypothesis_Status MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis"); // is there local hypothesis on me? - if ( GetSimilarAttached( _subShape, 0, theHypType ) ) + if ( getSimilarAttached( _subShape, 0, theHypType ) ) return SMESH_Hypothesis::HYP_OK; @@ -1988,7 +2109,7 @@ SMESH_Hypothesis::Hypothesis_Status for (; it.More(); it.Next()) { const TopoDS_Shape& ancestor = it.Value(); - const SMESH_Hypothesis* hyp = GetSimilarAttached( ancestor, 0, theHypType ); + const SMESH_Hypothesis* hyp = getSimilarAttached( ancestor, 0, theHypType ); if ( hyp ) { if ( aPrevWithHyp.IsNull() || aPrevWithHyp.IsSame( ancestor )) @@ -2005,14 +2126,26 @@ SMESH_Hypothesis::Hypothesis_Status return SMESH_Hypothesis::HYP_OK; } +//================================================================================ +/*! + * \brief Constructor of OwnListenerData + */ +//================================================================================ + +SMESH_subMesh::OwnListenerData::OwnListenerData( SMESH_subMesh* sm, EventListener* el): + mySubMesh( sm ), + myMeshID( sm ? sm->GetFather()->GetId() : -1 ), + mySubMeshID( sm ? sm->GetId() : -1 ), + myListener( el ) +{ +} + //================================================================================ /*! * \brief Sets an event listener and its data to a submesh * \param listener - the listener to store * \param data - the listener data to store * \param where - the submesh to store the listener and it's data - * \param deleteListener - if true then the listener will be deleted as - * it is removed from where submesh * * It remembers the submesh where it puts the listener in order to delete * them when HYP_OK algo_state is lost @@ -2025,8 +2158,8 @@ void SMESH_subMesh::SetEventListener(EventListener* listener, SMESH_subMesh* where) { if ( listener && where ) { - where->SetEventListener( listener, data ); - myOwnListeners.push_back( make_pair( where, listener )); + where->setEventListener( listener, data ); + _ownListeners.push_back( OwnListenerData( where, listener )); } } @@ -2040,18 +2173,32 @@ 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 = - myEventListeners.find( listener ); - if ( l_d != myEventListeners.end() ) { + _eventListeners.find( listener ); + if ( l_d != _eventListeners.end() ) { EventListenerData* curData = l_d->second; if ( curData && curData != data && curData->IsDeletable() ) delete curData; l_d->second = data; } - else - myEventListeners.insert( make_pair( listener, data )); + 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->IsDeletable() ) + delete l_d->first; + _eventListeners.erase( l_d ); + break; + } + _eventListeners.insert( make_pair( listener, data )); + } } //================================================================================ @@ -2065,12 +2212,29 @@ void SMESH_subMesh::SetEventListener(EventListener* listener, EventListenerData* EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) const { map< EventListener*, EventListenerData* >::const_iterator l_d = - myEventListeners.find( listener ); - if ( l_d != myEventListeners.end() ) + _eventListeners.find( listener ); + if ( l_d != _eventListeners.end() ) return l_d->second; return 0; } +//================================================================================ +/*! + * \brief Return an event listener data + * \param listenerName - the listener name + * \retval EventListenerData* - found data, maybe NULL + */ +//================================================================================ + +EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerName) const +{ + map< EventListener*, EventListenerData* >::const_iterator l_d = _eventListeners.begin(); + for ( ; l_d != _eventListeners.end(); ++l_d ) + if ( listenerName == l_d->first->GetName() ) + return l_d->second; + return 0; +} + //================================================================================ /*! * \brief Notify stored event listeners on the occured event @@ -2080,17 +2244,25 @@ EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) */ //================================================================================ -void SMESH_subMesh::NotifyListenersOnEvent( const int event, +void SMESH_subMesh::notifyListenersOnEvent( const int event, const event_type eventType, SMESH_Hypothesis* hyp) { - map< EventListener*, EventListenerData* >::iterator l_d = myEventListeners.begin(); - for ( ; l_d != myEventListeners.end(); ++l_d ) - if ( (*l_d).first->myBusySM.insert( this ).second ) + map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.begin(); + for ( ; l_d != _eventListeners.end(); ) + { + std::pair< EventListener*, EventListenerData* > li_da = *l_d++; /* copy to enable removal + of a listener from + _eventListeners by + its ProcessEvent() */ + if ( li_da.first->myBusySM.insert( this ).second ) { - l_d->first->ProcessEvent( event, eventType, this, l_d->second, hyp ); - l_d->first->myBusySM.erase( this ); + const size_t nbListenersBefore = _eventListeners.size(); + 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 } + } } //================================================================================ @@ -2103,11 +2275,20 @@ void SMESH_subMesh::NotifyListenersOnEvent( const int event, void SMESH_subMesh::DeleteEventListener(EventListener* listener) { map< EventListener*, EventListenerData* >::iterator l_d = - myEventListeners.find( listener ); - if ( l_d != myEventListeners.end() ) { - if ( l_d->first && l_d->first->IsDeletable() ) delete l_d->first; - if ( l_d->second && l_d->second->IsDeletable() ) delete l_d->second; - myEventListeners.erase( l_d ); + _eventListeners.find( listener ); + 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 ); } } @@ -2117,12 +2298,42 @@ void SMESH_subMesh::DeleteEventListener(EventListener* listener) */ //================================================================================ -void SMESH_subMesh::DeleteOwnListeners() +void SMESH_subMesh::deleteOwnListeners() +{ + list< OwnListenerData >::iterator d; + for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d ) + { + if ( !_father->MeshExists( d->myMeshID )) + continue; + if ( _father->GetId() == d->myMeshID && !_father->GetSubMeshContaining( d->mySubMeshID )) + continue; + d->mySubMesh->DeleteEventListener( d->myListener ); + } + _ownListeners.clear(); +} + +//======================================================================= +//function : loadDependentMeshes +//purpose : loads dependent meshes on SUBMESH_LOADED event +//======================================================================= + +void SMESH_subMesh::loadDependentMeshes() { - list< pair< SMESH_subMesh*, EventListener* > >::iterator sm_l; - for ( sm_l = myOwnListeners.begin(); sm_l != myOwnListeners.end(); ++sm_l) - sm_l->first->DeleteEventListener( sm_l->second ); - myOwnListeners.clear(); + list< OwnListenerData >::iterator d; + for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d ) + if ( _father != d->mySubMesh->_father ) + d->mySubMesh->_father->Load(); + + // map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.begin(); + // for ( ; l_d != _eventListeners.end(); ++l_d ) + // if ( l_d->second ) + // { + // const list& smList = l_d->second->mySubMeshes; + // list::const_iterator sm = smList.begin(); + // for ( ; sm != smList.end(); ++sm ) + // if ( _father != (*sm)->_father ) + // (*sm)->_father->Load(); + // } } //================================================================================ @@ -2215,28 +2426,29 @@ 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 )); } } //================================================================================ /*! - * \brief Find common submeshes (based on shared subshapes with other + * \brief Find common submeshes (based on shared sub-shapes with other * \param theOther submesh to check * \param theSetOfCommon set of common submesh */