#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_Failure.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:
ComputeStateEngine( CHECK_COMPUTE_STATE );
}
+//=======================================================================
+/*!
+ * \brief Return true if no mesh entities is bound to the submesh
+ */
+//=======================================================================
+
+bool SMESH_subMesh::IsEmpty() const
+{
+ if (SMESHDS_SubMesh * subMeshDS = ((SMESH_subMesh*)this)->GetSubMeshDS())
+ return (!subMeshDS->GetNodes()->more() && !subMeshDS->GetElements()->more());
+ return true;
+}
+
//=======================================================================
//function : IsMeshComputed
//purpose : check if _subMeshDS contains mesh elements
case TopAbs_SOLID:
{
//MESSAGE("solid");
- for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
- exp.Next())
- {
- InsertDependence(exp.Current());
+ if(_father->HasShapeToMesh()) {
+ for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
+ exp.Next())
+ {
+ InsertDependence(exp.Current());
+ }
}
break;
}
{
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;
+ }
if ( aHypDim <= aShapeDim )
return true;
-// if ( aHypDim < aShapeDim )
-// return ( _father->IsMainShape( _subShape ));
return false;
}
return SMESH_Hypothesis::HYP_OK;
}
// 0D hypothesis
- else if ( _algoState == HYP_OK ) { // update default _algoState
- _algoState = NO_ALGO;
- algo = gen->GetAlgo(*_father, _subShape);
- if ( algo ) {
- _algoState = MISSING_HYP;
- if ( algo->CheckHypothesis(*_father,_subShape, aux_ret))
- _algoState = HYP_OK;
+ else if ( _algoState == HYP_OK ) {
+ // update default _algoState
+ if ( event != REMOVE_FATHER_ALGO )
+ {
+ _algoState = NO_ALGO;
+ algo = gen->GetAlgo(*_father, _subShape);
+ if ( algo ) {
+ _algoState = MISSING_HYP;
+ if ( event == REMOVE_FATHER_HYP ||
+ algo->CheckHypothesis(*_father,_subShape, aux_ret))
+ _algoState = HYP_OK;
+ }
}
}
}
// -------------------------------------------
algo = static_cast< SMESH_Algo* >( anHyp );
if ( !_father->HasShapeToMesh() && algo->NeedShape() )
- return SMESH_Hypothesis::HYP_BAD_GEOMETRY;
+ return SMESH_Hypothesis::HYP_NEED_SHAPE;
// ----------------------
// check mesh conformity
// ----------------------
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())
CleanDependants();
ComputeStateEngine( CLEAN );
CleanDependsOn();
+ ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
}
}
}
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() )
+ if ( !upperAlgo->NeedDescretBoundary() && !upperAlgo->SupportSubmeshes())
ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO;
}
// is algo hiding?
- if ( ret == SMESH_Hypothesis::HYP_OK && !algo->NeedDescretBoundary() ) {
+ if ( ret == SMESH_Hypothesis::HYP_OK &&
+ !algo->NeedDescretBoundary() &&
+ !algo->SupportSubmeshes()) {
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 ))
if ( stateChange && oldAlgoState == HYP_OK ) { // hyp becomes KO
DeleteOwnListeners();
+ SetIsAlwaysComputed( false );
if (_subShape.ShapeType() == TopAbs_VERTEX ) {
// restore default states
_algoState = HYP_OK;
SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
//EAP: a wire (dim==1) should notify edges (dim==1)
//EAP: int dim = SMESH_Gen::GetShapeDim(_subShape);
- if (_subShape.ShapeType() < TopAbs_EDGE ) // wire,face etc
+ //if (_subShape.ShapeType() < TopAbs_EDGE ) // wire,face etc
{
SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
while ( smIt->more() ) {
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 ) {
+ CleanDependants();
+ cleanSubMesh( this );
+ }
+ else
+ _computeState = COMPUTE_OK;
}
else if ( event == COMPUTE && !_alwaysComputed ) {
const TopoDS_Vertex & V = TopoDS::Vertex( _subShape );
SetAlgoState(MISSING_HYP);
break;
}
+ TopoDS_Shape shape = _subShape;
// check submeshes needed
if (_father->HasShapeToMesh() ) {
- bool subComputed = SubMeshesComputed();
+ bool subComputed = false;
+ if (!algo->OnlyUnaryInput())
+ shape = GetCollection( gen, algo, subComputed );
+ else
+ subComputed = SubMeshesComputed();
ret = ( algo->NeedDescretBoundary() ? subComputed :
+ algo->SupportSubmeshes() ? true :
( !subComputed || _father->IsNotConformAllowed() ));
if (!ret) {
_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);
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);
- }
+ ret = algo->Compute((*_father), shape);
}
- if ( !ret )
+ if ( !ret && _computeError->IsOK() ) // algo can set _computeError of submesh
_computeError = algo->GetComputeError();
}
- catch (Standard_Failure& exc) {
+ catch ( std::bad_alloc& exc ) {
+ MESSAGE("std::bad_alloc thrown inside algo->Compute()");
+ if ( _computeError ) {
+ _computeError->myName = COMPERR_MEMORY_PB;
+ //_computeError->myComment = exc.what();
+ }
+ cleanSubMesh( this );
+ throw exc;
+ }
+ catch ( Standard_OutOfMemory& exc ) {
+ MESSAGE("Standard_OutOfMemory thrown inside algo->Compute()");
+ if ( _computeError ) {
+ _computeError->myName = COMPERR_MEMORY_PB;
+ //_computeError->myComment = exc.what();
+ }
+ cleanSubMesh( this );
+ throw std::bad_alloc();
+ }
+ 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();
_computeError->myName = COMPERR_SLM_EXCEPTION;
_computeError->myComment = S_ex.what();
}
- catch ( std::bad_alloc& exc ) {
- if ( _computeError ) {
- _computeError->myName = COMPERR_MEMORY_PB;
- _computeError->myComment = exc.what();
- }
- throw exc;
- }
catch ( std::exception& exc ) {
if ( !_computeError ) _computeError = SMESH_ComputeError::New();
_computeError->myName = COMPERR_STD_EXCEPTION;
else
ret = false;
}
- if ( ret && _computeError && !_computeError->IsOK() ) {
- ret = false;
- }
- if (ret) { // check if anything was built
+ if (ret && !_alwaysComputed && shape == _subShape) { // 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:
switch (event)
{
case MODIF_ALGO_STATE:
+ algo = gen->GetAlgo((*_father), _subShape);
+ if (algo && !algo->NeedDescretBoundary())
+ CleanDependsOn(); // clean sub-meshes with event CLEAN
if (_algoState == HYP_OK)
_computeState = READY_TO_COMPUTE;
else
//=======================================================================
/*!
- * \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() )
{
- 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 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, sm->GetSubShape() ))
+ noErrors = false;
+ UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
+ }
+ }
+ }
+ }
+ {
+ // 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
- cout << "Subshape vertices (first 10):" << endl;
- TopTools_IndexedMapOfShape vMap;
- TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
- for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) {
- gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
- cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
- }
+ MESSAGE_BEGIN ( text );
+ // Show vertices location of a failed shape
+ TopTools_IndexedMapOfShape vMap;
+ TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
+ MESSAGE_ADD ( "Subshape vertices " << ( vMap.Extent()>10 ? "(first 10):" : ":") );
+ for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) {
+ gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
+ MESSAGE_ADD ( "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " "
+ << P.X() << " " << P.Y() << " " << P.Z() << " " );
+ }
#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;
}
// meshed at once along with _subShape
//=======================================================================
-TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo)
+TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen,
+ SMESH_Algo* theAlgo,
+ bool & theSubComputed)
{
MESSAGE("SMESH_subMesh::GetCollection");
- ASSERT (!theAlgo->NeedDescretBoundary());
+
+ theSubComputed = SubMeshesComputed();
TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
{
SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
- if (anAlgo == theAlgo &&
- anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp)
+ if (strcmp( anAlgo->GetName(), theAlgo->GetName()) == 0 && // same algo
+ anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) // same hyps
aBuilder.Add( aCompound, S );
+ if ( !subMesh->SubMeshesComputed() )
+ theSubComputed = false;
}
}
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:;
}
SMESH_subMesh* prepend,
SMESH_subMesh* append): myIt(subIt),myAppend(append)
{
- myCur = prepend ? prepend : myIt->more() ? myIt->next() : 0;
+ myCur = prepend ? prepend : myIt->more() ? myIt->next() : append;
+ if ( myCur == append ) append = 0;
}
/// Return true if and only if there are other object in this iterator
virtual bool more()