#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <TopExp.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <TopTools_ListOfShape.hxx>
-#include <TopTools_MapOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
#include <gp_Pnt.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Iterator.hxx>
#include <Standard_OutOfMemory.hxx>
#include <Standard_ErrorHandler.hxx>
using namespace std;
+//=============================================================================
+/*!
+ * \brief Allocate some memory at construction and release it at destruction.
+ * Is used to be able to continue working after mesh generation breaks due to
+ * lack of memory
+ */
+//=============================================================================
+
+struct MemoryReserve
+{
+ char* myBuf;
+ MemoryReserve(): myBuf( new char[1024*1024*2] ){}
+ ~MemoryReserve() { delete [] myBuf; }
+};
+
//=============================================================================
/*!
* default constructor:
if ( !meshDS->AddHypothesis(_subShape, anHyp))
return SMESH_Hypothesis::HYP_ALREADY_EXIST;
-
- // Serve Propagation of 1D hypothesis
- // NOTE: it is possible to re-implement Propagation using EventListener
- if (event == ADD_HYP) {
- bool isPropagationOk = true;
- bool isPropagationHyp = ( strcmp( "Propagation", anHyp->GetName() ) == 0 );
-
- if ( isPropagationHyp ) {
- TopExp_Explorer exp (_subShape, TopAbs_EDGE);
- TopTools_MapOfShape aMap;
- for (; exp.More(); exp.Next()) {
- if (aMap.Add(exp.Current())) {
- if (!_father->BuildPropagationChain(exp.Current())) {
- isPropagationOk = false;
- }
- }
- }
- }
- else if (anHyp->GetDim() == 1) { // Only 1D hypothesis can be propagated
- TopExp_Explorer exp (_subShape, TopAbs_EDGE);
- TopTools_MapOfShape aMap;
- for (; exp.More(); exp.Next()) {
- if (aMap.Add(exp.Current())) {
- TopoDS_Shape aMainEdge;
- if (_father->IsPropagatedHypothesis(exp.Current(), aMainEdge)) {
- isPropagationOk = _father->RebuildPropagationChains();
- } else if (_father->IsPropagationHypothesis(exp.Current())) {
- isPropagationOk = _father->BuildPropagationChain(exp.Current());
- } else {
- }
- }
- }
- } else {
- }
-
- if ( isPropagationOk ) {
- if ( isPropagationHyp )
- return ret; // nothing more to do for "Propagation" hypothesis
- }
- else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) {
- ret = SMESH_Hypothesis::HYP_CONCURENT;
- }
- } // Serve Propagation of 1D hypothesis
}
// --------------------------
if (!meshDS->RemoveHypothesis(_subShape, anHyp))
return SMESH_Hypothesis::HYP_OK; // nothing changes
- // Serve Propagation of 1D hypothesis
- // NOTE: it is possible to re-implement Propagation using EventListener
- if (event == REMOVE_HYP)
- {
- bool isPropagationOk = true;
- SMESH_HypoFilter propagFilter( SMESH_HypoFilter::HasName( "Propagation" ));
- bool isPropagationHyp = propagFilter.IsOk( anHyp, _subShape );
-
- if ( isPropagationHyp )
- {
- TopExp_Explorer exp (_subShape, TopAbs_EDGE);
- TopTools_MapOfShape aMap;
- for (; exp.More(); exp.Next()) {
- if (aMap.Add(exp.Current()) &&
- !_father->GetHypothesis( exp.Current(), propagFilter, true )) {
- // no more Propagation on the current edge
- if (!_father->RemovePropagationChain(exp.Current())) {
- return SMESH_Hypothesis::HYP_UNKNOWN_FATAL;
- }
- }
- }
- // rebuild propagation chains, because removing one
- // chain can resolve concurention, existing before
- isPropagationOk = _father->RebuildPropagationChains();
- }
- else if (anHyp->GetDim() == 1) // Only 1D hypothesis can be propagated
- {
- isPropagationOk = _father->RebuildPropagationChains();
- }
-
- if ( isPropagationOk ) {
- if ( isPropagationHyp )
- return ret; // nothing more to do for "Propagation" hypothesis
- }
- else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) {
- ret = SMESH_Hypothesis::HYP_CONCURENT;
- }
- } // Serve Propagation of 1D hypothesis
- else // event == REMOVE_ALGO
+ if (event == REMOVE_ALGO)
{
algo = dynamic_cast<SMESH_Algo*> (anHyp);
if (!algo->NeedDescretBoundary())
if ( stateChange && oldAlgoState == HYP_OK ) { // hyp becomes KO
DeleteOwnListeners();
+ SetIsAlwaysComputed( false );
if (_subShape.ShapeType() == TopAbs_VERTEX ) {
// restore default states
_algoState = HYP_OK;
while (itn->more()) {
const SMDS_MeshNode * node = itn->next();
//MESSAGE( " RM node: "<<node->GetID());
- if ( node->NbInverseNodes() == 0 )
+ if ( node->NbInverseElements() == 0 )
meshDS->RemoveFreeNode(node, subMeshDS);
else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another
meshDS->RemoveNode(node);
_computeState = READY_TO_COMPUTE;
SMESHDS_SubMesh* smDS = GetSubMeshDS();
if ( smDS && smDS->NbNodes() ) {
- _computeState = COMPUTE_OK;
+ if ( event == CLEAN ) // this occures for algo which !NeedDescretBoundary() (PAL19272)
+ cleanSubMesh( this );
+ else
+ _computeState = COMPUTE_OK;
}
else if ( event == COMPUTE && !_alwaysComputed ) {
const TopoDS_Vertex & V = TopoDS::Vertex( _subShape );
_computeState = FAILED_TO_COMPUTE;
if ( !algo->NeedDescretBoundary() )
_computeError =
- SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH,"Unexpected submesh",algo);
+ SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH,
+ "Unexpected computed submesh",algo);
break;
}
}
// compute
- CleanDependants();
- RemoveSubMeshElementsAndNodes();
+// CleanDependants(); for "UseExisting_*D" algos
+// RemoveSubMeshElementsAndNodes();
ret = false;
_computeState = FAILED_TO_COMPUTE;
_computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
+ TopoDS_Shape shape = _subShape;
try {
#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
OCC_CATCH_SIGNALS;
#endif
algo->InitComputeError();
+ MemoryReserve aMemoryReserve;
+ SMDS_Mesh::CheckMemory();
if ( !_father->HasShapeToMesh() ) // no shape
{
SMESH_MesherHelper helper( *_father );
- helper.SetSubShape( _subShape );
+ helper.SetSubShape( shape );
helper.SetElementsOnShape( true );
ret = algo->Compute(*_father, &helper );
}
else
{
- if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput()) {
- ret = ApplyToCollection( algo, GetCollection( gen, algo ) );
- break;
- }
- else {
- ret = algo->Compute((*_father), _subShape);
+ if (!algo->OnlyUnaryInput()) {
+ shape = GetCollection( gen, algo );
}
+ ret = algo->Compute((*_father), shape);
}
if ( !ret )
_computeError = algo->GetComputeError();
}
catch ( std::bad_alloc& exc ) {
+ printf("std::bad_alloc thrown inside algo->Compute()\n");
if ( _computeError ) {
_computeError->myName = COMPERR_MEMORY_PB;
//_computeError->myComment = exc.what();
}
+ cleanSubMesh( this );
throw exc;
}
catch ( Standard_OutOfMemory& exc ) {
+ printf("Standard_OutOfMemory thrown inside algo->Compute()\n");
if ( _computeError ) {
- _computeError->myName = COMPERR_MEMORY_PB;
+ _computeError->myName = COMPERR_MEMORY_PB;
//_computeError->myComment = exc.what();
}
- throw exc;
+ cleanSubMesh( this );
+ throw std::bad_alloc();
}
- catch (Standard_Failure& exc) {
+ catch (Standard_Failure& ex) {
if ( !_computeError ) _computeError = SMESH_ComputeError::New();
_computeError->myName = COMPERR_OCC_EXCEPTION;
- _computeError->myComment = exc.GetMessageString();
+ _computeError->myComment += ex.DynamicType()->Name();
+ if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) {
+ _computeError->myComment += ": ";
+ _computeError->myComment += ex.GetMessageString();
+ }
}
catch ( SALOME_Exception& S_ex ) {
if ( !_computeError ) _computeError = SMESH_ComputeError::New();
else
ret = false;
}
- if ( ret && _computeError && !_computeError->IsOK() ) {
- ret = false;
- }
if (ret && !_alwaysComputed) { // check if anything was built
ret = ( GetSubMeshDS() && ( GetSubMeshDS()->NbElements() || GetSubMeshDS()->NbNodes() ));
}
- if (!ret)
+ bool isComputeErrorSet = !CheckComputeError( algo, shape );
+ if (!ret && !isComputeErrorSet)
{
// Set _computeError
if ( !_computeError )
_computeError = SMESH_ComputeError::New();
if ( _computeError->IsOK() )
_computeError->myName = COMPERR_ALGO_FAILED;
+ _computeState = FAILED_TO_COMPUTE;
}
- else
+ if (ret)
{
_computeError.reset();
- UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
}
- if ( !algo->NeedDescretBoundary() )
- UpdateSubMeshState( ret ? COMPUTE_OK : FAILED_TO_COMPUTE );
- CheckComputeError( algo );
+ UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
}
break;
case CLEAN:
//=======================================================================
/*!
- * \brief Update compute_state by _computeError
+ * \brief Update compute_state by _computeError and send proper events to
+ * dependent submeshes
+ * \retval bool - true if _computeError is NOT set
*/
//=======================================================================
-bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo)
+bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& theShape)
{
- bool noErrors = ( !_computeError || _computeError->IsOK() );
- if ( !noErrors )
+ bool noErrors = true;
+
+ if ( !theShape.IsNull() )
+ {
+ // Check state of submeshes
+ if ( !theAlgo->NeedDescretBoundary())
+ {
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
+ while ( smIt->more() )
+ if ( !smIt->next()->CheckComputeError( theAlgo ))
+ noErrors = false;
+ }
+
+ // Check state of neighbours
+ if ( !theAlgo->OnlyUnaryInput() &&
+ theShape.ShapeType() == TopAbs_COMPOUND &&
+ !theShape.IsSame( _subShape ))
+ {
+ for (TopoDS_Iterator subIt( theShape ); subIt.More(); subIt.Next()) {
+ SMESH_subMesh* sm = _father->GetSubMesh( subIt.Value() );
+ if ( sm != this ) {
+ if ( !sm->CheckComputeError( theAlgo ))
+ noErrors = false;
+ UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
+ }
+ }
+ }
+ }
{
- if ( !_computeError->myAlgo )
- _computeError->myAlgo = theAlgo;
-
- // Show error
- SMESH_Comment text;
- text << theAlgo->GetName() << " failed on subshape #" << _Id << " with error ";
- if (_computeError->IsCommon() )
- text << _computeError->CommonName();
+ // Check my state
+ if ( !_computeError || _computeError->IsOK() )
+ {
+ _computeState = COMPUTE_OK;
+ }
else
- text << _computeError->myName;
- if ( _computeError->myComment.size() > 0 )
- text << " \"" << _computeError->myComment << "\"";
+ {
+ if ( !_computeError->myAlgo )
+ _computeError->myAlgo = theAlgo;
+
+ // Show error
+ SMESH_Comment text;
+ text << theAlgo->GetName() << " failed on subshape #" << _Id << " with error ";
+ if (_computeError->IsCommon() )
+ text << _computeError->CommonName();
+ else
+ text << _computeError->myName;
+ if ( _computeError->myComment.size() > 0 )
+ text << " \"" << _computeError->myComment << "\"";
#ifdef _DEBUG_
- cout << text << endl;
- // Show vertices location of a failed shape
- TopTools_IndexedMapOfShape vMap;
- TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
- cout << "Subshape vertices " << ( vMap.Extent()>10 ? "(first 10):" : ":") << endl;
- for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) {
- gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
- cout << "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " ";
- cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
- }
+ cout << text << endl;
+ // Show vertices location of a failed shape
+ TopTools_IndexedMapOfShape vMap;
+ TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
+ cout << "Subshape vertices " << ( vMap.Extent()>10 ? "(first 10):" : ":") << endl;
+ for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) {
+ gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
+ cout << "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " ";
+ cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
+ }
#else
- INFOS( text );
+ INFOS( text );
#endif
- _computeState = FAILED_TO_COMPUTE;
- }
- else
- {
- _computeState = COMPUTE_OK;
- }
- // Check state of submeshes
- if ( !theAlgo->NeedDescretBoundary() /*&& theAlgo->OnlyUnaryInput()*/ ) {
- SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
- while ( smIt->more() )
- if ( !smIt->next()->CheckComputeError( theAlgo ))
- noErrors = false;
+ _computeState = FAILED_TO_COMPUTE;
+ noErrors = false;
+ }
}
return noErrors;
}
TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo)
{
MESSAGE("SMESH_subMesh::GetCollection");
- ASSERT (!theAlgo->NeedDescretBoundary());
TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
map< EventListener*, EventListenerData* >::iterator l_d =
myEventListeners.find( listener );
if ( l_d != myEventListeners.end() ) {
- if ( l_d->second && l_d->second->IsDeletable() )
- delete l_d->second;
+ EventListenerData* curData = l_d->second;
+ if ( curData && curData != data && curData->IsDeletable() )
+ delete curData;
l_d->second = data;
}
else
eventType == SMESH_subMesh::COMPUTE_EVENT)
{
ASSERT( data->mySubMeshes.front() != subMesh );
+ list<SMESH_subMesh*>::iterator smIt = data->mySubMeshes.begin();
+ list<SMESH_subMesh*>::iterator smEnd = data->mySubMeshes.end();
switch ( event ) {
case SMESH_subMesh::CLEAN:
- data->mySubMeshes.front()->ComputeStateEngine( event );
+ for ( ; smIt != smEnd; ++ smIt)
+ (*smIt)->ComputeStateEngine( event );
break;
case SMESH_subMesh::COMPUTE:
if ( subMesh->GetComputeState() == SMESH_subMesh::COMPUTE_OK )
- data->mySubMeshes.front()->ComputeStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
+ for ( ; smIt != smEnd; ++ smIt)
+ (*smIt)->ComputeStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
break;
default:;
}