X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_subMesh.cxx;h=4da6bf9ffda286faae4ac101d6de3d94caaca1d2;hp=9afb7677c3abfe8150aaea2e52626104122a413b;hb=bd39d7c3ed2581f5b6eaf6dca1cb581f767c8f50;hpb=31ca0b3e3be91c2e0e9ea2ec70c828f373bfb086 diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 9afb7677c..4da6bf9ff 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -104,6 +104,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 +116,6 @@ SMESH_subMesh::SMESH_subMesh(int Id, SMESH_subMesh::~SMESH_subMesh() { - MESSAGE("SMESH_subMesh::~SMESH_subMesh"); - // **** deleteOwnListeners(); } @@ -355,6 +355,48 @@ 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; +} + +//================================================================================ +/*! + * \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; +} + //============================================================================= /*! * @@ -501,6 +543,23 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() return _mapDepend; } +//================================================================================ +/*! + * \brief Return a key for SMESH_subMesh::_mapDepend map + */ +//================================================================================ + +namespace { + int dependsOnMapKey( const SMESH_subMesh* sm ) + { + int type = sm->GetSubShape().ShapeType(); + int ordType = 9 - type; // 2 = Vertex, 8 = CompSolid + int cle = sm->GetId(); + cle += 10000000 * ordType; // sort map by ordType then index + return cle; + } +} + //============================================================================= /*! * For simple Shapes (solid, face, edge): add subMesh into dependence list. @@ -510,10 +569,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() void SMESH_subMesh::insertDependence(const TopoDS_Shape aSubShape) { SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape); - int type = aSubShape.ShapeType(); - int ordType = 9 - type; // 2 = Vertex, 8 = CompSolid - int cle = aSubMesh->GetId(); - cle += 10000000 * ordType; // sort map by ordType then index + int cle = dependsOnMapKey( aSubMesh ); if ( _mapDepend.find( cle ) == _mapDepend.end()) { _mapDepend[cle] = aSubMesh; @@ -522,19 +578,28 @@ void SMESH_subMesh::insertDependence(const TopoDS_Shape aSubShape) } } +//================================================================================ +/*! + * \brief Return \c true if \a this sub-mesh depends on \a other + */ +//================================================================================ + +bool SMESH_subMesh::DependsOn( const SMESH_subMesh* other ) const +{ + return other ? _mapDepend.count( dependsOnMapKey( other )) : false; +} + //============================================================================= /*! - * + * Return a shape of \a this sub-mesh */ //============================================================================= const TopoDS_Shape & SMESH_subMesh::GetSubShape() const { - //MESSAGE("SMESH_subMesh::GetSubShape"); - return _subShape; + return _subShape; } - //======================================================================= //function : CanAddHypothesis //purpose : return true if theHypothesis can be attached to me: @@ -1049,6 +1114,9 @@ SMESH_Hypothesis::Hypothesis_Status if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK algo->SetEventListener( this ); + if ( event == REMOVE_ALGO || event == REMOVE_FATHER_ALGO ) + _algo = 0; + notifyListenersOnEvent( event, ALGO_EVENT, anHyp ); if ( stateChange && oldAlgoState == HYP_OK ) { // hyp becomes KO @@ -1071,6 +1139,8 @@ SMESH_Hypothesis::Hypothesis_Status if (stateChange || modifiedHyp) ComputeStateEngine(MODIF_ALGO_STATE); + _realComputeCost = ( _algoState == HYP_OK ) ? computeCost() : 0; + return ret; } @@ -1248,8 +1318,7 @@ 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 (dim < 1) return; if (isMain) { const map < int, SMESH_subMesh * >&subMeshes = DependsOn(); @@ -1261,8 +1330,9 @@ void SMESH_subMesh::DumpAlgoState(bool isMain) sm->DumpAlgoState(false); } } - int type = _subShape.ShapeType(); - MESSAGE("dim = " << dim << " type of shape " << type); + //int type = _subShape.ShapeType(); + MESSAGE("dim = " << SMESH_Gen::GetShapeDim(_subShape) << + " type of shape " << _subShape.ShapeType()); switch (_algoState) { case NO_ALGO: @@ -1309,7 +1379,7 @@ static void cleanSubMesh( SMESH_subMesh * subMesh ) const SMDS_MeshElement * elt = ite->next(); //MESSAGE( " RM elt: "<GetID()<<" ( "<NbNodes()<<" )" ); //meshDS->RemoveElement(elt); - meshDS->RemoveFreeElement(elt, subMeshDS); + meshDS->RemoveFreeElement(elt, 0); } SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes(); @@ -1317,10 +1387,11 @@ static void cleanSubMesh( SMESH_subMesh * subMesh ) const SMDS_MeshNode * node = itn->next(); //MESSAGE( " RM node: "<GetID()); if ( node->NbInverseElements() == 0 ) - meshDS->RemoveFreeNode(node, subMeshDS); + meshDS->RemoveFreeNode(node, 0); else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another meshDS->RemoveNode(node); } + subMeshDS->Clear(); } } } @@ -1348,6 +1419,9 @@ bool SMESH_subMesh::ComputeStateEngine(int event) default:; } + if ( event == CLEAN ) + _alwaysComputed = false; // Unset 'true' set by MergeNodes() (issue 0022182) + if (_subShape.ShapeType() == TopAbs_VERTEX) { _computeState = READY_TO_COMPUTE; @@ -1456,13 +1530,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 ); + if ( event == COMPUTE /*&& + ( algo->NeedDiscreteBoundary() || algo->SupportSubmeshes() )*/) + shape = getCollection( gen, algo, subComputed, subFailed, algo->SubMeshesToCompute()); else subComputed = SubMeshesComputed( & subFailed ); } @@ -1478,12 +1553,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(); @@ -1491,10 +1569,10 @@ bool SMESH_subMesh::ComputeStateEngine(int event) _computeState = FAILED_TO_COMPUTE; _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo); try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif + algo->InitComputeError(); + MemoryReserve aMemoryReserve; SMDS_Mesh::CheckMemory(); Kernel_Utils::Localizer loc; @@ -1509,8 +1587,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) { ret = algo->Compute((*_father), shape); } - if ( !_computeError || ( !ret && _computeError->IsOK() ) ) // algo can set _computeError of submesh - _computeError = algo->GetComputeError(); + // algo can set _computeError of submesh + _computeError = SMESH_ComputeError::Worst( _computeError, algo->GetComputeError() ); } catch ( ::SMESH_ComputeError& comperr ) { cout << " SMESH_ComputeError caught" << endl; @@ -1563,6 +1641,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 ) @@ -1572,7 +1652,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) @@ -1887,7 +1970,7 @@ bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, if ( _computeState != COMPUTE_OK ) { if ( _subShape.ShapeType() == TopAbs_EDGE && - BRep_Tool::Degenerated( TopoDS::Edge( _subShape )) ) + SMESH_Algo::isDegenerated( TopoDS::Edge( _subShape )) ) _computeState = COMPUTE_OK; else if ( theComputeOK ) _computeError = SMESH_ComputeError::New(COMPERR_NO_MESH_ON_SHAPE,"",theAlgo); @@ -2022,7 +2105,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 ); @@ -2036,17 +2120,20 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy // put in a compound all shapes with the same hypothesis assigned - // and a good ComputState + // and a good ComputeState TopoDS_Compound aCompound; BRep_Builder aBuilder; aBuilder.MakeCompound( aCompound ); + theSubs.clear(); + TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() ); for ( ; anExplorer.More(); anExplorer.Next() ) { const TopoDS_Shape& S = anExplorer.Current(); SMESH_subMesh* subMesh = _father->GetSubMesh( S ); + theSubs.push_back( subMesh ); if ( subMesh == this ) { aBuilder.Add( aCompound, S ); @@ -2199,7 +2286,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; @@ -2212,16 +2299,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; } @@ -2229,16 +2331,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; } @@ -2255,19 +2372,22 @@ void SMESH_subMesh::notifyListenersOnEvent( const int event, const event_type eventType, SMESH_Hypothesis* hyp) { - map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.begin(); - for ( ; l_d != _eventListeners.end(); ) + list< pair< EventListener*, EventListenerData* > > eventListeners( _eventListeners.begin(), + _eventListeners.end()); + list< pair< EventListener*, EventListenerData* > >::iterator l_d = eventListeners.begin(); + for ( ; l_d != eventListeners.end(); ++l_d ) { - std::pair< EventListener*, EventListenerData* > li_da = *l_d++; /* copy to enable removal - of a listener from - _eventListeners by - its ProcessEvent() */ + std::pair< EventListener*, EventListenerData* > li_da = *l_d; + if ( !_eventListeners.count( li_da.first )) continue; + if ( li_da.first->myBusySM.insert( this ).second ) { - const size_t nbListenersBefore = _eventListeners.size(); + const bool isDeletable = li_da.first->IsDeletable(); + li_da.first->ProcessEvent( event, eventType, this, li_da.second, hyp ); - if ( nbListenersBefore == _eventListeners.size() ) - li_da.first->myBusySM.erase( this ); // a listener hopefully not removed + + if ( !isDeletable || _eventListeners.count( li_da.first )) + li_da.first->myBusySM.erase( this ); // a listener is hopefully not dead } } }