-// Copyright (C) 2007-2013 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
// 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
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
-#include <gp_Pnt.hxx>
-#include <TopExp_Explorer.hxx>
#include <TopoDS_Iterator.hxx>
+#include <gp_Pnt.hxx>
#include <Standard_OutOfMemory.hxx>
#include <Standard_ErrorHandler.hxx>
_algoState = NO_ALGO;
_computeState = NOT_READY;
}
+ _computeCost = 0; // how costly is to compute this sub-mesh
+ _realComputeCost = 0;
}
//=============================================================================
SMESH_subMesh::~SMESH_subMesh()
{
- MESSAGE("SMESH_subMesh::~SMESH_subMesh");
- // ****
deleteOwnListeners();
}
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;
}
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;
+}
+
//=============================================================================
/*!
*
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)
{
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;
}
}
+//================================================================================
+/*!
+ * \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:
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;
}
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;
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;
{
// 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<int, SMESH_subMesh*>::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 ( 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
if (stateChange || modifiedHyp)
ComputeStateEngine(MODIF_ALGO_STATE);
+ _realComputeCost = ( _algoState == HYP_OK ) ? computeCost() : 0;
+
return ret;
}
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())
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();
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:
const SMDS_MeshElement * elt = ite->next();
//MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
//meshDS->RemoveElement(elt);
- meshDS->RemoveFreeElement(elt, subMeshDS);
+ meshDS->RemoveFreeElement(elt, 0);
}
SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
const SMDS_MeshNode * node = itn->next();
//MESSAGE( " RM node: "<<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();
}
}
}
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 );
}
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();
_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;
{
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;
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 )
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)
case CHECK_COMPUTE_STATE:
if ( IsMeshComputed() )
_computeState = COMPUTE_OK;
+ else if ( _computeError && _computeError->IsKO() )
+ _computeState = FAILED_TO_COMPUTE;
break;
default:
ASSERT(0);
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);
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 );
}
}
{
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);
}
}
}
TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
SMESH_Algo* theAlgo,
bool & theSubComputed,
- bool & theSubFailed)
+ bool & theSubFailed,
+ std::vector<SMESH_subMesh*>& theSubs)
{
theSubComputed = SubMeshesComputed( & theSubFailed );
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 );
}
else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
{
- SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
+ SMESH_Algo* anAlgo = theGen->GetAlgo( subMesh );
if (strcmp( anAlgo->GetName(), theAlgo->GetName()) == 0 && // same algo
anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) // same hyps
aBuilder.Add( aCompound, S );
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;
/*!
* \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;
}
/*!
* \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;
}
li_da.first->ProcessEvent( event, eventType, this, li_da.second, hyp );
- if ( !isDeletable || !_eventListeners.count( li_da.first ))
+ if ( !isDeletable || _eventListeners.count( li_da.first ))
li_da.first->myBusySM.erase( this ); // a listener is hopefully not dead
}
}
}
}
+//================================================================================
+/*!
+ * \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