X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_subMesh.cxx;h=8c2702a47b3e9121c6fdac9c43333ed5434be5a9;hp=9d0c236e08454755a9b9f6b596e5f5adc2e14472;hb=897fdb92b6c3bd5cfc749bde222355992ecffc13;hpb=10a6101340f612ab64b73ed32728a392acfbda5f diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 9d0c236e0..8c2702a47 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2015 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 @@ -47,13 +47,14 @@ #include #include #include +#include #include #include +#include #include #include -#include -#include #include +#include #include #include @@ -104,6 +105,8 @@ SMESH_subMesh::SMESH_subMesh(int Id, _algoState = NO_ALGO; _computeState = NOT_READY; } + _computeCost = 0; // how costly is to compute this sub-mesh + _realComputeCost = 0; } //============================================================================= @@ -114,8 +117,6 @@ SMESH_subMesh::SMESH_subMesh(int Id, SMESH_subMesh::~SMESH_subMesh() { - MESSAGE("SMESH_subMesh::~SMESH_subMesh"); - // **** deleteOwnListeners(); } @@ -195,7 +196,10 @@ SMESH_subMesh *SMESH_subMesh::GetFirstToCompute() SMESH_Algo* SMESH_subMesh::GetAlgo() const { if ( !_algo ) - ((SMESH_subMesh*)this)->_algo = _father->GetGen()->GetAlgo(*_father, _subShape); + { + SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this ); + me->_algo = _father->GetGen()->GetAlgo( me ); + } return _algo; } @@ -355,29 +359,47 @@ bool SMESH_subMesh::SubMeshesComputed(bool * isFailedToCompute/*=0*/) const 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; +} -// 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; -// } +//================================================================================ +/*! + * \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; +} //============================================================================= /*! @@ -393,148 +415,108 @@ bool SMESH_subMesh::SubMeshesComputed(bool * isFailedToCompute/*=0*/) const const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() { - if (_dependenceAnalysed) + if ( _dependenceAnalysed || !_father->HasShapeToMesh() ) return _mapDepend; - //MESSAGE("SMESH_subMesh::DependsOn"); - int type = _subShape.ShapeType(); - //SCRUTE(type); switch (type) { case TopAbs_COMPOUND: + { + list< TopoDS_Shape > compounds( 1, _subShape ); + list< TopoDS_Shape >::iterator comp = compounds.begin(); + for ( ; comp != compounds.end(); ++comp ) { - //MESSAGE("compound"); - for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();exp.Next()) - { - 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 - else - for (TopExp_Explorer expF(exp.Current(), TopAbs_FACE); expF.More();expF.Next()) - 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()); - } - for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();exp.Next()) - { - insertDependence(exp.Current()); - } - for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX, TopAbs_EDGE); exp.More();exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_COMPSOLID: - { - //MESSAGE("compsolid"); - for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More(); exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_SHELL: - { - //MESSAGE("shell"); - for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More(); exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_WIRE: - { - //MESSAGE("wire"); - for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More(); exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_SOLID: - { - //MESSAGE("solid"); - if(_father->HasShapeToMesh()) { - for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();exp.Next()) + for ( TopoDS_Iterator sub( *comp ); sub.More(); sub.Next() ) + switch ( sub.Value().ShapeType() ) { - insertDependence(exp.Current()); + case TopAbs_COMPOUND: compounds.push_back( sub.Value() ); break; + case TopAbs_COMPSOLID: insertDependence( sub.Value(), TopAbs_SOLID ); break; + case TopAbs_SOLID: insertDependence( sub.Value(), TopAbs_SOLID ); break; + case TopAbs_SHELL: insertDependence( sub.Value(), TopAbs_FACE ); break; + case TopAbs_FACE: insertDependence( sub.Value(), TopAbs_FACE ); break; + case TopAbs_WIRE: insertDependence( sub.Value(), TopAbs_EDGE ); break; + case TopAbs_EDGE: insertDependence( sub.Value(), TopAbs_EDGE ); break; + case TopAbs_VERTEX: insertDependence( sub.Value(), TopAbs_VERTEX ); break; + default:; } - } - break; - } - case TopAbs_FACE: - { - //MESSAGE("face"); - for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_EDGE: - { - //MESSAGE("edge"); - for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More(); exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_VERTEX: - { - break; - } - default: - { - break; } } + break; + case TopAbs_COMPSOLID: insertDependence( _subShape, TopAbs_SOLID ); break; + case TopAbs_SOLID: insertDependence( _subShape, TopAbs_FACE ); break; + case TopAbs_SHELL: insertDependence( _subShape, TopAbs_FACE ); break; + case TopAbs_FACE: insertDependence( _subShape, TopAbs_EDGE ); break; + case TopAbs_WIRE: insertDependence( _subShape, TopAbs_EDGE ); break; + case TopAbs_EDGE: insertDependence( _subShape, TopAbs_VERTEX ); break; + default:; + } _dependenceAnalysed = true; 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. */ //============================================================================= -void SMESH_subMesh::insertDependence(const TopoDS_Shape aSubShape) +void SMESH_subMesh::insertDependence(const TopoDS_Shape aShape, + TopAbs_ShapeEnum aSubType) { - 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 - if ( _mapDepend.find( cle ) == _mapDepend.end()) + TopExp_Explorer sub( aShape, aSubType ); + for ( ; sub.More(); sub.Next() ) { - _mapDepend[cle] = aSubMesh; - const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn(); - _mapDepend.insert( subMap.begin(), subMap.end() ); + SMESH_subMesh *aSubMesh = _father->GetSubMesh( sub.Current() ); + int cle = dependsOnMapKey( aSubMesh ); + if ( _mapDepend.find( cle ) == _mapDepend.end()) + { + _mapDepend[cle] = aSubMesh; + const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn(); + _mapDepend.insert( subMap.begin(), subMap.end() ); + } } } +//================================================================================ +/*! + * \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: @@ -601,11 +583,17 @@ bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis, return false; } -//============================================================================= +//================================================================================ /*! - * + * \brief Treats modification of hypotheses definition + * \param [in] event - what happens + * \param [in] anHyp - a hypothesis + * \return SMESH_Hypothesis::Hypothesis_Status - a treatment result. + * + * Optional description of a problematic situation (if any) can be retrieved + * via GetComputeError(). */ -//============================================================================= +//================================================================================ SMESH_Hypothesis::Hypothesis_Status SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp) @@ -670,7 +658,7 @@ 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 )) + if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis( this, filter, true )) if ( !curAlgo->NeedDiscreteBoundary() ) algoRequiringCleaning = curAlgo; } @@ -684,7 +672,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)) @@ -713,6 +701,9 @@ SMESH_Hypothesis::Hypothesis_Status if (!isApplicableHyp) return ret; // not applicable hypotheses do not change algo state + if (( algo = GetAlgo())) + algo->InitComputeError(); + switch (_algoState) { @@ -877,7 +868,7 @@ SMESH_Hypothesis::Hypothesis_Status // ret should be fatal: anHyp was not added ret = SMESH_Hypothesis::HYP_INCOMPATIBLE; } - else if (!_father->IsUsedHypothesis( anHyp, this )) + else if (!_father->IsUsedHypothesis( anHyp, this )) ret = SMESH_Hypothesis::HYP_INCOMPATIBLE; if (SMESH_Hypothesis::IsStatusFatal( ret )) @@ -899,7 +890,7 @@ SMESH_Hypothesis::Hypothesis_Status f.Init( SMESH_HypoFilter::IsAlgo() ); f.And( SMESH_HypoFilter::IsApplicableTo( _subShape )); f.AndNot( SMESH_HypoFilter::Is( algo )); - const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true ); + const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( this, f, true ); if (prevAlgo && string(algo->GetName()) != string(prevAlgo->GetName()) ) modifiedHyp = true; @@ -958,7 +949,7 @@ SMESH_Hypothesis::Hypothesis_Status f.Init( SMESH_HypoFilter::IsAlgo() ); f.And( SMESH_HypoFilter::IsApplicableTo( _subShape )); f.AndNot( SMESH_HypoFilter::Is( algo )); - const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true ); + const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( this, f, true ); if (prevAlgo && string(algo->GetName()) != string(prevAlgo->GetName()) ) modifiedHyp = true; @@ -1024,26 +1015,32 @@ SMESH_Hypothesis::Hypothesis_Status { // is algo hidden? SMESH_Gen* gen = _father->GetGen(); - TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape )); - for ( ; ( ret == SMESH_Hypothesis::HYP_OK && it.More()); it.Next() ) { - if ( SMESH_Algo* upperAlgo = gen->GetAlgo( *_father, it.Value() )) + const std::vector< SMESH_subMesh * > & ancestors = GetAncestors(); + for ( size_t iA = 0; ( ret == SMESH_Hypothesis::HYP_OK && iA < ancestors.size()); ++iA ) { + if ( SMESH_Algo* upperAlgo = ancestors[ iA ]->GetAlgo() ) if ( !upperAlgo->NeedDiscreteBoundary() && !upperAlgo->SupportSubmeshes()) ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO; } // is algo hiding? if ( ret == SMESH_Hypothesis::HYP_OK && !algo->NeedDiscreteBoundary() && - !algo->SupportSubmeshes()) { + !algo->SupportSubmeshes()) + { TopoDS_Shape algoAssignedTo, otherAssignedTo; - gen->GetAlgo( *_father, _subShape, &algoAssignedTo ); + gen->GetAlgo( this, &algoAssignedTo ); map::reverse_iterator i_sm = _mapDepend.rbegin(); for ( ; ( ret == SMESH_Hypothesis::HYP_OK && i_sm != _mapDepend.rend()) ; ++i_sm ) - if ( gen->GetAlgo( *_father, i_sm->second->_subShape, &otherAssignedTo ) && + if ( gen->GetAlgo( i_sm->second, &otherAssignedTo ) && SMESH_MesherHelper::IsSubShape( /*sub=*/otherAssignedTo, /*main=*/algoAssignedTo )) ret = SMESH_Hypothesis::HYP_HIDING_ALGO; } } + if ( _algo ) { // get an error description set by _algo->CheckHypothesis() + _computeError = _algo->GetComputeError(); + _algo->InitComputeError(); + } + bool stateChange = ( _algoState != oldAlgoState ); if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK @@ -1071,8 +1068,10 @@ SMESH_Hypothesis::Hypothesis_Status ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE ); } - if (stateChange || modifiedHyp) - ComputeStateEngine(MODIF_ALGO_STATE); + if ( stateChange || modifiedHyp ) + ComputeStateEngine( MODIF_ALGO_STATE ); + + _realComputeCost = ( _algoState == HYP_OK ) ? computeCost() : 0; return ret; } @@ -1110,16 +1109,16 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo) for (; itsub.More(); itsub.Next()) { // loop on adjacent subShapes - TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( itsub.Value() )); - for (; it.More(); it.Next()) + const std::vector< SMESH_subMesh * > & ancestors = GetAncestors(); + for ( size_t iA = 0; iA < ancestors.size(); ++iA ) { - const TopoDS_Shape& adjacent = it.Value(); + const TopoDS_Shape& adjacent = ancestors[ iA ]->GetSubShape(); if ( _subShape.IsSame( adjacent )) continue; if ( adjacent.ShapeType() != _subShape.ShapeType()) break; // check algo attached to smAdjacent - SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent); + SMESH_Algo * algo = ancestors[ iA ]->GetAlgo(); if (algo && !algo->NeedDiscreteBoundary() && algo->OnlyUnaryInput()) @@ -1141,14 +1140,24 @@ void SMESH_subMesh::setAlgoState(algo_state state) _algoState = state; } -//============================================================================= +//================================================================================ /*! + * \brief Send an event to sub-meshes + * \param [in] event - the event + * \param [in] anHyp - an hypothesis + * \param [in] exitOnFatal - to stop iteration on sub-meshes if a sub-mesh + * reports a fatal result + * \return SMESH_Hypothesis::Hypothesis_Status - the worst result * + * Optional description of a problematic situation (if any) can be retrieved + * via GetComputeError(). */ -//============================================================================= +//================================================================================ + SMESH_Hypothesis::Hypothesis_Status - SMESH_subMesh::SubMeshesAlgoStateEngine(int event, - SMESH_Hypothesis * anHyp) + SMESH_subMesh::SubMeshesAlgoStateEngine(int event, + SMESH_Hypothesis * anHyp, + bool exitOnFatal) { SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK; //EAP: a wire (dim==1) should notify edges (dim==1) @@ -1157,10 +1166,16 @@ SMESH_Hypothesis::Hypothesis_Status { SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); while ( smIt->more() ) { - SMESH_Hypothesis::Hypothesis_Status ret2 = - smIt->next()->AlgoStateEngine(event, anHyp); + SMESH_subMesh* sm = smIt->next(); + SMESH_Hypothesis::Hypothesis_Status ret2 = sm->AlgoStateEngine(event, anHyp); if ( ret2 > ret ) + { ret = ret2; + _computeError = sm->_computeError; + sm->_computeError.reset(); + if ( exitOnFatal && SMESH_Hypothesis::IsStatusFatal( ret )) + break; + } } } return ret; @@ -1251,48 +1266,32 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ ) void SMESH_subMesh::DumpAlgoState(bool isMain) { - int dim = SMESH_Gen::GetShapeDim(_subShape); -// if (dim < 1) return; - if (isMain) - { - const map < int, SMESH_subMesh * >&subMeshes = DependsOn(); - - map < int, SMESH_subMesh * >::const_iterator itsub; - for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++) - { - SMESH_subMesh *sm = (*itsub).second; - sm->DumpAlgoState(false); - } - } - int type = _subShape.ShapeType(); - MESSAGE("dim = " << dim << " type of shape " << type); - switch (_algoState) - { - case NO_ALGO: - MESSAGE(" AlgoState = NO_ALGO"); - break; - case MISSING_HYP: - MESSAGE(" AlgoState = MISSING_HYP"); - break; - case HYP_OK: - MESSAGE(" AlgoState = HYP_OK"); - break; - } - switch (_computeState) - { - case NOT_READY: - MESSAGE(" ComputeState = NOT_READY"); - break; - case READY_TO_COMPUTE: - MESSAGE(" ComputeState = READY_TO_COMPUTE"); - break; - case COMPUTE_OK: - MESSAGE(" ComputeState = COMPUTE_OK"); - break; - case FAILED_TO_COMPUTE: - MESSAGE(" ComputeState = FAILED_TO_COMPUTE"); - break; - } + if (isMain) + { + const map < int, SMESH_subMesh * >&subMeshes = DependsOn(); + + map < int, SMESH_subMesh * >::const_iterator itsub; + for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++) + { + SMESH_subMesh *sm = (*itsub).second; + sm->DumpAlgoState(false); + } + } + MESSAGE("dim = " << SMESH_Gen::GetShapeDim(_subShape) << + " type of shape " << _subShape.ShapeType()); + switch (_algoState) + { + case NO_ALGO : MESSAGE(" AlgoState = NO_ALGO"); break; + case MISSING_HYP : MESSAGE(" AlgoState = MISSING_HYP"); break; + case HYP_OK : MESSAGE(" AlgoState = HYP_OK");break; + } + switch (_computeState) + { + case NOT_READY : MESSAGE(" ComputeState = NOT_READY");break; + case READY_TO_COMPUTE : MESSAGE(" ComputeState = READY_TO_COMPUTE");break; + case COMPUTE_OK : MESSAGE(" ComputeState = COMPUTE_OK");break; + case FAILED_TO_COMPUTE: MESSAGE(" ComputeState = FAILED_TO_COMPUTE");break; + } } //================================================================================ @@ -1312,7 +1311,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(); @@ -1320,10 +1319,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(); } } } @@ -1462,13 +1462,14 @@ 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, subFailed = false; if (!algo->OnlyUnaryInput()) { if ( event == COMPUTE /*&& ( algo->NeedDiscreteBoundary() || algo->SupportSubmeshes() )*/) - shape = getCollection( gen, algo, subComputed, subFailed ); + shape = getCollection( gen, algo, subComputed, subFailed, algo->SubMeshesToCompute()); else subComputed = SubMeshesComputed( & subFailed ); } @@ -1484,12 +1485,15 @@ bool SMESH_subMesh::ComputeStateEngine(int event) if ( !algo->NeedDiscreteBoundary() && !subFailed ) _computeError = SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH, - "Unexpected computed submesh",algo); + "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(); @@ -1497,10 +1501,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; @@ -1515,8 +1519,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; @@ -1569,6 +1573,8 @@ 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 ) @@ -1578,7 +1584,10 @@ bool SMESH_subMesh::ComputeStateEngine(int event) 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) @@ -1658,6 +1667,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) case CHECK_COMPUTE_STATE: if ( IsMeshComputed() ) _computeState = COMPUTE_OK; + else if ( _computeError && _computeError->IsKO() ) + _computeState = FAILED_TO_COMPUTE; break; default: ASSERT(0); @@ -1747,10 +1758,13 @@ bool SMESH_subMesh::ComputeStateEngine(int event) removeSubMeshElementsAndNodes(); break; case SUBMESH_COMPUTED: // allow retry compute - if (_algoState == HYP_OK) - _computeState = READY_TO_COMPUTE; - else - _computeState = NOT_READY; + if ( IsEmpty() ) // 23061 + { + if (_algoState == HYP_OK) + _computeState = READY_TO_COMPUTE; + else + _computeState = NOT_READY; + } break; case SUBMESH_RESTORED: ComputeSubMeshStateEngine( SUBMESH_RESTORED ); @@ -1893,7 +1907,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); @@ -1956,47 +1970,41 @@ void SMESH_subMesh::ComputeSubMeshStateEngine(int event, const bool includeSelf) void SMESH_subMesh::updateDependantsState(const compute_event theEvent) { - TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape )); - for (; it.More(); it.Next()) + const std::vector< SMESH_subMesh * > & ancestors = GetAncestors(); + for ( size_t iA = 0; iA < ancestors.size(); ++iA ) { - const TopoDS_Shape& ancestor = it.Value(); - if ( SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor)) - aSubMesh->ComputeStateEngine( theEvent ); + ancestors[ iA ]->ComputeStateEngine( theEvent ); } } -//============================================================================= -/*! - * - */ -//============================================================================= +//======================================================================= +//function : cleanDependants +//purpose : +//======================================================================= void SMESH_subMesh::cleanDependants() { int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1; - TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape )); - for (; it.More(); it.Next()) + const std::vector< SMESH_subMesh * > & ancestors = GetAncestors(); + for ( size_t iA = 0; iA < ancestors.size(); ++iA ) { - const TopoDS_Shape& ancestor = it.Value(); - if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) { + const TopoDS_Shape& ancestor = ancestors[ iA ]->GetSubShape(); + if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) + { // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEAN) // will erase mesh on other shapes in a compound - if ( ancestor.ShapeType() >= TopAbs_SOLID ) { - SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor); - if (aSubMesh && - !aSubMesh->IsEmpty() ) // prevent infinite CLEAN via event lesteners - aSubMesh->ComputeStateEngine(CLEAN); - } + if ( ancestor.ShapeType() >= TopAbs_SOLID && + !ancestors[ iA ]->IsEmpty() ) // prevent infinite CLEAN via event lesteners + ancestors[ iA ]->ComputeStateEngine(CLEAN); } } } -//============================================================================= -/*! - * - */ -//============================================================================= +//======================================================================= +//function : removeSubMeshElementsAndNodes +//purpose : +//======================================================================= void SMESH_subMesh::removeSubMeshElementsAndNodes() { @@ -2028,7 +2036,8 @@ void SMESH_subMesh::removeSubMeshElementsAndNodes() TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo, bool & theSubComputed, - bool & theSubFailed) + bool & theSubFailed, + std::vector& theSubs) { theSubComputed = SubMeshesComputed( & theSubFailed ); @@ -2037,34 +2046,41 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, if ( mainShape.IsSame( _subShape )) return _subShape; - const bool ignoreAuxiliaryHyps = false; + const bool skipAuxHyps = false; list aUsedHyp = - theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy + theAlgo->GetUsedHypothesis( *_father, _subShape, skipAuxHyps ); // 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 ); - TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() ); - for ( ; anExplorer.More(); anExplorer.Next() ) + theSubs.clear(); + + SMESH_subMeshIteratorPtr smIt = _father->GetSubMesh( mainShape )->getDependsOnIterator(false); + while ( smIt->more() ) { - const TopoDS_Shape& S = anExplorer.Current(); - SMESH_subMesh* subMesh = _father->GetSubMesh( S ); + SMESH_subMesh* subMesh = smIt->next(); + const TopoDS_Shape& S = subMesh->_subShape; + if ( S.ShapeType() != this->_subShape.ShapeType() ) + continue; + theSubs.push_back( subMesh ); if ( subMesh == this ) { aBuilder.Add( aCompound, S ); } else if ( subMesh->GetComputeState() == READY_TO_COMPUTE ) { - SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S ); - if (strcmp( anAlgo->GetName(), theAlgo->GetName()) == 0 && // same algo - anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) // same hyps + SMESH_Algo* anAlgo = subMesh->GetAlgo(); + if (( anAlgo->IsSameName( *theAlgo )) && // same algo + ( anAlgo->GetUsedHypothesis( *_father, S, skipAuxHyps ) == aUsedHyp )) // same hyps + { aBuilder.Add( aCompound, S ); - if ( !subMesh->SubMeshesComputed() ) - theSubComputed = false; + if ( !subMesh->SubMeshesComputed() ) + theSubComputed = false; + } } } @@ -2205,7 +2221,7 @@ void SMESH_subMesh::setEventListener(EventListener* listener, EventListenerData* curData = l_d->second; if ( curData && curData != data && curData->IsDeletable() ) delete curData; - if ( l_d->first->IsDeletable() ) + if ( l_d->first != listener && l_d->first->IsDeletable() ) delete l_d->first; _eventListeners.erase( l_d ); break; @@ -2218,16 +2234,31 @@ void SMESH_subMesh::setEventListener(EventListener* listener, /*! * \brief Return an event listener data * \param listener - the listener whose data is + * \param myOwn - if \c true, returns a listener set by this sub-mesh, + * else returns a listener listening to events of this sub-mesh * \retval EventListenerData* - found data, maybe NULL */ //================================================================================ -EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) const +EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener, + const bool myOwn) const { - map< EventListener*, EventListenerData* >::const_iterator l_d = - _eventListeners.find( listener ); - if ( l_d != _eventListeners.end() ) - return l_d->second; + if ( myOwn ) + { + list< OwnListenerData >::const_iterator d; + for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d ) + { + if ( d->myListener == listener && _father->MeshExists( d->myMeshID )) + return d->mySubMesh->GetEventListenerData( listener, !myOwn ); + } + } + else + { + map< EventListener*, EventListenerData* >::const_iterator l_d = + _eventListeners.find( listener ); + if ( l_d != _eventListeners.end() ) + return l_d->second; + } return 0; } @@ -2235,16 +2266,31 @@ EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) /*! * \brief Return an event listener data * \param listenerName - the listener name + * \param myOwn - if \c true, returns a listener set by this sub-mesh, + * else returns a listener listening to events of this sub-mesh * \retval EventListenerData* - found data, maybe NULL */ //================================================================================ -EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerName) const +EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerName, + const bool myOwn) 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; + if ( myOwn ) + { + list< OwnListenerData >::const_iterator d; + for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d ) + { + if ( _father->MeshExists( d->myMeshID ) && listenerName == d->myListener->GetName()) + return d->mySubMesh->GetEventListenerData( listenerName, !myOwn ); + } + } + else + { + 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; } @@ -2319,9 +2365,8 @@ 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 )) + SMESH_Mesh* mesh = _father->FindMesh( d->myMeshID ); + if ( !mesh || !mesh->GetSubMeshContaining( d->mySubMeshID )) continue; d->mySubMesh->DeleteEventListener( d->myListener ); } @@ -2463,6 +2508,44 @@ SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeS } } +//================================================================================ +/*! + * \brief Returns ancestor sub-meshes. Finds them if not yet found. + */ +//================================================================================ + +const std::vector< SMESH_subMesh * > & SMESH_subMesh::GetAncestors() const +{ + if ( _ancestors.empty() && + !_subShape.IsSame( _father->GetShapeToMesh() )) + { + const TopTools_ListOfShape& ancShapes = _father->GetAncestors( _subShape ); + + SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this ); + me->_ancestors.reserve( ancShapes.Extent() ); + + TopTools_MapOfShape map; + + for ( TopTools_ListIteratorOfListOfShape it( ancShapes ); it.More(); it.Next() ) + if ( SMESH_subMesh* sm = _father->GetSubMeshContaining( it.Value() )) + if ( map.Add( it.Value() )) + me->_ancestors.push_back( sm ); + } + + return _ancestors; +} + +//================================================================================ +/*! + * \brief Clears the vector of ancestor sub-meshes + */ +//================================================================================ + +void SMESH_subMesh::ClearAncestors() +{ + _ancestors.clear(); +} + //================================================================================ /*! * \brief Find common submeshes (based on shared sub-shapes with other @@ -2471,16 +2554,18 @@ SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeS */ //================================================================================ -bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther, +bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther, std::set& theSetOfCommon ) const { int oldNb = theSetOfCommon.size(); + // check main submeshes const map ::const_iterator otherEnd = theOther->_mapDepend.end(); if ( theOther->_mapDepend.find(this->GetId()) != otherEnd ) theSetOfCommon.insert( this ); if ( _mapDepend.find(theOther->GetId()) != _mapDepend.end() ) theSetOfCommon.insert( theOther ); + // check common submeshes map ::const_iterator mapIt = _mapDepend.begin(); for( ; mapIt != _mapDepend.end(); mapIt++ )