#include "SMESH_subMesh.hxx"
-#include "SMESH_subMeshEventListener.hxx"
-#include "SMESH_Gen.hxx"
-#include "SMESH_Mesh.hxx"
-#include "SMESH_Hypothesis.hxx"
#include "SMESH_Algo.hxx"
+#include "SMESH_Gen.hxx"
#include "SMESH_HypoFilter.hxx"
+#include "SMESH_Hypothesis.hxx"
+#include "SMESH_Mesh.hxx"
#include "SMESH_MesherHelper.hxx"
+#include "SMESH_subMeshEventListener.hxx"
+#include "SMESH_Comment.hxx"
+#include "SMDS_SetIterator.hxx"
#include "utilities.h"
#include "OpUtil.hxx"
#include <BRep_Builder.hxx>
-
+#include <BRep_Tool.hxx>
#include <TopExp.hxx>
-#include <TopoDS_Compound.hxx>
-#include <TopTools_MapOfShape.hxx>
-#include <TopTools_ListOfShape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
-
-#ifdef _DEBUG_
-#include <gp_Pnt.hxx>
-#include <BRep_Tool.hxx>
#include <TopoDS.hxx>
-#include <TopTools_IndexedMapOfShape.hxx>
-#endif
+#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:
const TopoDS_Shape & aSubShape)
{
_subShape = aSubShape;
- _meshDS = meshDS;
_subMeshDS = meshDS->MeshElements(_subShape); // may be null ...
_father = father;
_Id = Id;
{
MESSAGE("SMESH_subMesh::~SMESH_subMesh");
// ****
+ DeleteOwnListeners();
}
//=============================================================================
SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS()
{
// submesh appears in DS only when a mesher set nodes and elements on a shape
- return _subMeshDS ? _subMeshDS : _subMeshDS = _meshDS->MeshElements(_subShape); // may be null
+ return _subMeshDS ? _subMeshDS : _subMeshDS = _father->GetMeshDS()->MeshElements(_subShape); // may be null
}
//=============================================================================
SMESHDS_SubMesh* SMESH_subMesh::CreateSubMeshDS()
{
- if ( !GetSubMeshDS() )
- _meshDS->NewSubMesh( _meshDS->ShapeToIndex( _subShape ) );
-
+ if ( !GetSubMeshDS() ) {
+ SMESHDS_Mesh* meshDS = _father->GetMeshDS();
+ meshDS->NewSubMesh( meshDS->ShapeToIndex( _subShape ) );
+ }
return GetSubMeshDS();
}
SMESH_subMesh *SMESH_subMesh::GetFirstToCompute()
{
- const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
- SMESH_subMesh *firstToCompute = 0;
-
- map < int, SMESH_subMesh * >::const_iterator itsub;
- for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
- {
- SMESH_subMesh *sm = (*itsub).second;
- bool readyToCompute = (sm->GetComputeState() == READY_TO_COMPUTE);
- if (readyToCompute)
- {
- firstToCompute = sm;
- break;
- }
- }
- if (firstToCompute)
- {
- return firstToCompute; // a subMesh of this
- }
- if (_computeState == READY_TO_COMPUTE)
- {
- return this; // this
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(true,false);
+ while ( smIt->more() ) {
+ SMESH_subMesh *sm = smIt->next();
+ if ( sm->GetComputeState() == READY_TO_COMPUTE )
+ return sm;
}
return 0; // nothing to compute
}
// algo may bind a submesh not to _subShape, eg 3D algo
// sets nodes on SHELL while _subShape may be SOLID
+ SMESHDS_Mesh* meshDS = _father->GetMeshDS();
int dim = SMESH_Gen::GetShapeDim( _subShape );
int type = _subShape.ShapeType();
for ( ; type <= TopAbs_VERTEX; type++) {
TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
for ( ; exp.More(); exp.Next() )
{
- SMESHDS_SubMesh * smDS = _meshDS->MeshElements( exp.Current() );
- if ( smDS && ( smDS->NbElements() || smDS->NbNodes()))
- return true;
+ if ( SMESHDS_SubMesh * smDS = meshDS->MeshElements( exp.Current() ))
+ {
+ bool computed = (dim > 0) ? smDS->NbElements() : smDS->NbNodes();
+ if ( computed )
+ return true;
+ }
}
}
else
bool SMESH_subMesh::SubMeshesComputed()
{
- //MESSAGE("SMESH_subMesh::SubMeshesComputed");
- const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
-
int myDim = SMESH_Gen::GetShapeDim( _subShape );
int dimToCheck = myDim - 1;
bool subMeshesComputed = true;
// check subMeshes with upper dimension => reverse iteration
- map < int, SMESH_subMesh * >::const_reverse_iterator itsub;
- for (itsub = subMeshes.rbegin(); itsub != subMeshes.rend(); itsub++)
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true);
+ while ( smIt->more() )
{
- SMESH_subMesh *sm = (*itsub).second;
+ SMESH_subMesh *sm = smIt->next();
if ( sm->_alwaysComputed )
continue;
const TopoDS_Shape & ss = sm->GetSubShape();
bool SMESH_subMesh::SubMeshesReady()
{
- MESSAGE("SMESH_subMesh::SubMeshesReady");
- const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
-
bool subMeshesReady = true;
- map < int, SMESH_subMesh * >::const_iterator itsub;
- for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
- {
- SMESH_subMesh *sm = (*itsub).second;
- bool computeOk = ((sm->GetComputeState() == COMPUTE_OK)
- || (sm->GetComputeState() == READY_TO_COMPUTE));
+ 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;
*/
//=============================================================================
-const map < int, SMESH_subMesh * >&SMESH_subMesh::DependsOn()
+const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
{
if (_dependenceAnalysed)
return _mapDepend;
SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
- SMESH_Gen* gen =_father->GetGen();
- SMESH_Algo* algo = 0;
+ SMESHDS_Mesh* meshDS =_father->GetMeshDS();
+ SMESH_Gen* gen =_father->GetGen();
+ SMESH_Algo* algo = 0;
if (_subShape.ShapeType() == TopAbs_VERTEX )
{
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;
+ }
}
}
}
if ( /*!anHyp->IsAuxiliary() &&*/ GetSimilarAttached( _subShape, anHyp ) )
return SMESH_Hypothesis::HYP_ALREADY_EXIST;
- if ( !_meshDS->AddHypothesis(_subShape, anHyp))
+ 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 (event == REMOVE_HYP || event == REMOVE_ALGO)
{
- if (!_meshDS->RemoveHypothesis(_subShape, anHyp))
+ 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 );
}
}
}
if (algo->CheckHypothesis((*_father),_subShape, aux_ret))
SetAlgoState(HYP_OK);
else if ( algo->IsStatusFatal( aux_ret )) {
- _meshDS->RemoveHypothesis(_subShape, anHyp);
+ meshDS->RemoveHypothesis(_subShape, anHyp);
ret = aux_ret;
}
else
if ( algo->CheckHypothesis((*_father),_subShape, ret ))
SetAlgoState(HYP_OK);
if (SMESH_Hypothesis::IsStatusFatal( ret ))
- _meshDS->RemoveHypothesis(_subShape, anHyp);
+ meshDS->RemoveHypothesis(_subShape, anHyp);
else if (!_father->IsUsedHypothesis( anHyp, this ))
{
- _meshDS->RemoveHypothesis(_subShape, anHyp);
+ meshDS->RemoveHypothesis(_subShape, anHyp);
ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
}
break;
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status
SetAlgoState(HYP_OK);
else if ( algo->IsStatusFatal( aux_ret )) {
- _meshDS->RemoveHypothesis(_subShape, anHyp);
+ meshDS->RemoveHypothesis(_subShape, anHyp);
ret = aux_ret;
}
else
if (SMESH_Hypothesis::IsStatusFatal( ret ))
{
MESSAGE("do not add extra hypothesis");
- _meshDS->RemoveHypothesis(_subShape, anHyp);
+ meshDS->RemoveHypothesis(_subShape, anHyp);
}
else
{
if ( stateChange && oldAlgoState == HYP_OK ) { // hyp becomes KO
DeleteOwnListeners();
+ SetIsAlwaysComputed( false );
if (_subShape.ShapeType() == TopAbs_VERTEX ) {
// restore default states
_algoState = HYP_OK;
SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
SMESH_Hypothesis * anHyp)
{
- //MESSAGE("SMESH_subMesh::SubMeshesAlgoStateEngine");
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
{
- 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;
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
+ while ( smIt->more() ) {
SMESH_Hypothesis::Hypothesis_Status ret2 =
- sm->AlgoStateEngine(event, anHyp);
+ smIt->next()->AlgoStateEngine(event, anHyp);
if ( ret2 > ret )
ret = ret2;
}
void SMESH_subMesh::CleanDependsOn()
{
- //MESSAGE("SMESH_subMesh::CleanDependsOn");
-
- const map < int, SMESH_subMesh * >&dependson = DependsOn();
- map < int, SMESH_subMesh * >::const_iterator its;
- for (its = dependson.begin(); its != dependson.end(); its++)
- {
- SMESH_subMesh *sm = (*its).second;
- sm->ComputeStateEngine(CLEAN);
- }
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
+ while ( smIt->more() )
+ smIt->next()->ComputeStateEngine(CLEAN);
}
//=============================================================================
while (itn->more()) {
const SMDS_MeshNode * node = itn->next();
//MESSAGE( " RM node: "<<node->GetID());
- //meshDS->RemoveNode(node);
- meshDS->RemoveFreeNode(node, subMeshDS);
+ if ( node->NbInverseNodes() == 0 )
+ meshDS->RemoveFreeNode(node, subMeshDS);
+ else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another
+ meshDS->RemoveNode(node);
}
}
}
bool SMESH_subMesh::ComputeStateEngine(int event)
{
+ _computeError.reset();
+
//MESSAGE("SMESH_subMesh::ComputeStateEngine");
//SCRUTE(_computeState);
//SCRUTE(event);
if (_subShape.ShapeType() == TopAbs_VERTEX)
{
- if ( IsMeshComputed() )
+ _computeState = READY_TO_COMPUTE;
+ SMESHDS_SubMesh* smDS = GetSubMeshDS();
+ if ( smDS && smDS->NbNodes() ) {
_computeState = COMPUTE_OK;
- else
- _computeState = READY_TO_COMPUTE;
+ }
+ else if ( event == COMPUTE && !_alwaysComputed ) {
+ const TopoDS_Vertex & V = TopoDS::Vertex( _subShape );
+ gp_Pnt P = BRep_Tool::Pnt(V);
+ if ( SMDS_MeshNode * n = _father->GetMeshDS()->AddNode(P.X(), P.Y(), P.Z()) ) {
+ _father->GetMeshDS()->SetNodeOnVertex(n,_Id);
+ _computeState = COMPUTE_OK;
+ }
+ }
if ( event == MODIF_ALGO_STATE )
CleanDependants();
return true;
break;
}
// check submeshes needed
- if (_father->HasShapeToMesh() && algo->NeedDescretBoundary())
- ret = SubMeshesComputed();
- if (!ret)
- {
- MESSAGE("Some SubMeshes not computed");
- _computeState = FAILED_TO_COMPUTE;
- break;
+ if (_father->HasShapeToMesh() ) {
+ bool subComputed = SubMeshesComputed();
+ ret = ( algo->NeedDescretBoundary() ? subComputed :
+ ( !subComputed || _father->IsNotConformAllowed() ));
+ if (!ret) {
+ _computeState = FAILED_TO_COMPUTE;
+ if ( !algo->NeedDescretBoundary() )
+ _computeError =
+ SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH,
+ "Unexpected computed submesh",algo);
+ break;
+ }
}
// compute
- CleanDependants();
- RemoveSubMeshElementsAndNodes();
- {
- try {
+// 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;
+ OCC_CATCH_SIGNALS;
#endif
- if ( !_father->HasShapeToMesh() ) // no shape
- {
- SMESH_MesherHelper helper( *_father );
- helper.SetSubShape( _subShape );
- helper.SetElementsOnShape( true );
- ret = algo->Compute(*_father, &helper );
- }
- else {
- if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput())
- ret = ApplyToCollection( algo, GetCollection( gen, algo ) );
- else
- ret = algo->Compute((*_father), _subShape);
+ algo->InitComputeError();
+ MemoryReserve aMemoryReserve;
+ SMDS_Mesh::CheckMemory();
+ if ( !_father->HasShapeToMesh() ) // no shape
+ {
+ SMESH_MesherHelper helper( *_father );
+ helper.SetSubShape( shape );
+ helper.SetElementsOnShape( true );
+ ret = algo->Compute(*_father, &helper );
+ }
+ else
+ {
+ if (!algo->OnlyUnaryInput()) {
+ shape = GetCollection( gen, algo );
}
+ ret = algo->Compute((*_father), shape);
}
- catch (Standard_Failure) {
- MESSAGE( "Exception in algo->Compute() ");
+ 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->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 += 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::exception& exc ) {
+ if ( !_computeError ) _computeError = SMESH_ComputeError::New();
+ _computeError->myName = COMPERR_STD_EXCEPTION;
+ _computeError->myComment = exc.what();
+ }
+ catch ( ... ) {
+ if ( _computeError )
+ _computeError->myName = COMPERR_EXCEPTION;
+ else
ret = false;
- }
- }
- if (!ret)
+ }
+ if (ret && !_alwaysComputed) { // check if anything was built
+ ret = ( GetSubMeshDS() && ( GetSubMeshDS()->NbElements() || GetSubMeshDS()->NbNodes() ));
+ }
+ bool isComputeErrorSet = !CheckComputeError( algo, shape );
+ if (!ret && !isComputeErrorSet)
{
- MESSAGE("problem in algo execution: failed to compute");
- // release ALGO from responsibilty of partially built mesh
- RemoveSubMeshElementsAndNodes();
+ // Set _computeError
+ if ( !_computeError )
+ _computeError = SMESH_ComputeError::New();
+ if ( _computeError->IsOK() )
+ _computeError->myName = COMPERR_ALGO_FAILED;
_computeState = FAILED_TO_COMPUTE;
- if (!algo->NeedDescretBoundary())
- UpdateSubMeshState( FAILED_TO_COMPUTE );
-
-#ifdef _DEBUG_
- // Show vertices location of a failed shape
- cout << algo->GetName() << " failed on shape with the following vertices:" << endl;
- TopTools_IndexedMapOfShape vMap;
- TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
- for ( int iv = 1; iv <= vMap.Extent(); ++iv ) {
- gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
- cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
- }
-#endif
- break;
}
- else
+ if (ret)
{
- _computeState = COMPUTE_OK;
- UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
- if (!algo->NeedDescretBoundary())
- UpdateSubMeshState( COMPUTE_OK );
+ _computeError.reset();
}
+ UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
}
break;
case CLEAN:
case CLEAN:
CleanDependants(); // submeshes dependent on me should be cleaned as well
RemoveSubMeshElementsAndNodes();
- if (_algoState == HYP_OK)
- _computeState = READY_TO_COMPUTE;
- else
- _computeState = NOT_READY;
break;
case SUBMESH_COMPUTED: // allow retry compute
if (_algoState == HYP_OK)
return ret;
}
+//=======================================================================
+/*!
+ * \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, const TopoDS_Shape& theShape)
+{
+ 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
+ }
+ }
+ }
+ }
+ {
+ // Check my state
+ if ( !_computeError || _computeError->IsOK() )
+ {
+ _computeState = COMPUTE_OK;
+ }
+ else
+ {
+ 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;
+ }
+#else
+ INFOS( text );
+#endif
+ _computeState = FAILED_TO_COMPUTE;
+ noErrors = false;
+ }
+ }
+ return noErrors;
+}
+
//=======================================================================
//function : ApplyToCollection
//purpose : Apply theAlgo to all subshapes in theCollection
MESSAGE("SMESH_subMesh::ApplyToCollection");
ASSERT ( !theAlgo->NeedDescretBoundary() );
- bool ret = false;
-
+ if ( _computeError )
+ _computeError->myName = COMPERR_OK;
- ret = theAlgo->Compute( *_father, theCollection );
+ bool ok = theAlgo->Compute( *_father, theCollection );
// set _computeState of subshapes
TopExp_Explorer anExplorer( theCollection, _subShape.ShapeType() );
for ( ; anExplorer.More(); anExplorer.Next() )
{
- const TopoDS_Shape& aSubShape = anExplorer.Current();
- SMESH_subMesh* subMesh = _father->GetSubMeshContaining( aSubShape );
- if ( subMesh )
+ if ( SMESH_subMesh* subMesh = _father->GetSubMeshContaining( anExplorer.Current() ))
{
- if (ret)
- {
- subMesh->_computeState = COMPUTE_OK;
- subMesh->UpdateDependantsState( SUBMESH_COMPUTED );
- subMesh->UpdateSubMeshState( COMPUTE_OK );
- }
- else
+ bool localOK = subMesh->CheckComputeError( theAlgo );
+ if ( !ok && localOK && !subMesh->IsMeshComputed() )
{
- subMesh->_computeState = FAILED_TO_COMPUTE;
+ subMesh->_computeError = theAlgo->GetComputeError();
+ if ( subMesh->_computeError->IsOK() )
+ _computeError = SMESH_ComputeError::New(COMPERR_ALGO_FAILED);
+ localOK = CheckComputeError( theAlgo );
}
+ if ( localOK )
+ subMesh->UpdateDependantsState( SUBMESH_COMPUTED );
+ subMesh->UpdateSubMeshState( localOK ? COMPUTE_OK : FAILED_TO_COMPUTE );
}
}
- return ret;
+
+ return true;
}
void SMESH_subMesh::UpdateSubMeshState(const compute_state theState)
{
- const map<int, SMESH_subMesh*>& smMap = DependsOn();
- map<int, SMESH_subMesh*>::const_iterator itsub;
- for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
- {
- SMESH_subMesh* sm = (*itsub).second;
- sm->_computeState = theState;
- }
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
+ while ( smIt->more() )
+ smIt->next()->_computeState = theState;
}
//=======================================================================
void SMESH_subMesh::ComputeSubMeshStateEngine(int event)
{
- const map<int, SMESH_subMesh*>& smMap = DependsOn();
- map<int, SMESH_subMesh*>::const_iterator itsub;
- for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
- {
- SMESH_subMesh* sm = (*itsub).second;
- sm->ComputeStateEngine(event);
- }
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
+ while ( smIt->more() )
+ smIt->next()->ComputeStateEngine(event);
}
//=======================================================================
TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo)
{
MESSAGE("SMESH_subMesh::GetCollection");
- ASSERT (!theAlgo->NeedDescretBoundary());
TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
{
const TopoDS_Shape& S = anExplorer.Current();
SMESH_subMesh* subMesh = _father->GetSubMesh( S );
- SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
-
- if (subMesh->GetComputeState() == READY_TO_COMPUTE &&
- anAlgo == theAlgo &&
- anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp)
+ if ( subMesh == this )
{
aBuilder.Add( aCompound, S );
}
+ else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
+ {
+ SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
+ if (anAlgo == theAlgo &&
+ anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp)
+ aBuilder.Add( aCompound, S );
+ }
}
return aCompound;
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
const int eventType,
SMESH_subMesh* subMesh,
EventListenerData* data,
- SMESH_Hypothesis* /*hyp*/)
+ const SMESH_Hypothesis* /*hyp*/)
{
if ( data && !data->mySubMeshes.empty() &&
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:;
}
}
}
+
+namespace {
+
+ //================================================================================
+ /*!
+ * \brief Iterator over submeshes and optionally prepended or appended one
+ */
+ //================================================================================
+
+ struct _Iterator : public SMDS_Iterator<SMESH_subMesh*>
+ {
+ _Iterator(SMDS_Iterator<SMESH_subMesh*>* subIt,
+ SMESH_subMesh* prepend,
+ SMESH_subMesh* append): myIt(subIt),myAppend(append)
+ {
+ myCur = prepend ? prepend : myIt->more() ? myIt->next() : 0;
+ }
+ /// Return true if and only if there are other object in this iterator
+ virtual bool more()
+ {
+ return myCur;
+ }
+ /// Return the current object and step to the next one
+ virtual SMESH_subMesh* next()
+ {
+ SMESH_subMesh* res = myCur;
+ if ( myIt->more() ) { myCur = myIt->next(); }
+ else { myCur = myAppend; myAppend = 0; }
+ return res;
+ }
+ /// ~
+ ~_Iterator()
+ { delete myIt; }
+ ///
+ SMESH_subMesh *myAppend, *myCur;
+ SMDS_Iterator<SMESH_subMesh*> *myIt;
+ };
+}
+
+//================================================================================
+/*!
+ * \brief Return iterator on the submeshes this one depends on
+ * \param includeSelf - this submesh to be returned also
+ * \param reverse - if true, complex shape submeshes go first
+ */
+//================================================================================
+
+SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeSelf,
+ const bool reverse)
+{
+ SMESH_subMesh *prepend=0, *append=0;
+ if ( includeSelf ) {
+ if ( reverse ) prepend = this;
+ else append = this;
+ }
+ typedef map < int, SMESH_subMesh * > TMap;
+ if ( reverse )
+ {
+ return SMESH_subMeshIteratorPtr
+ ( new _Iterator( new SMDS_mapReverseIterator<TMap>( DependsOn() ), prepend, append ));
+ }
+ {
+ return SMESH_subMeshIteratorPtr
+ ( new _Iterator( new SMDS_mapIterator<TMap>( DependsOn() ), prepend, append ));
+ }
+}