From: eap Date: Tue, 10 Apr 2007 14:06:02 +0000 (+0000) Subject: PAL13330( When mesh generation does not success, trace where ) X-Git-Tag: V3_2_6pre4~31 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=8b19a88a83e0ec70376f1aa94a51c3afe01b1fe3;p=modules%2Fsmesh.git PAL13330( When mesh generation does not success, trace where ) compute errors management --- diff --git a/src/SMESH/SMESH_Gen.cxx b/src/SMESH/SMESH_Gen.cxx index 9c8c864dc..3c34f2e63 100644 --- a/src/SMESH/SMESH_Gen.cxx +++ b/src/SMESH/SMESH_Gen.cxx @@ -122,134 +122,67 @@ SMESH_Mesh* SMESH_Gen::CreateMesh(int theStudyId, bool theIsEmbeddedMode) return aMesh; } -//================================================================================ -/*! - * \brief Compute submesh - * \param sm - submesh - * \retval bool - is a success - */ -//================================================================================ - -bool SMESH_Gen::Compute(::SMESH_subMesh& sm) -{ - if ( sm.GetSubShape().ShapeType() == TopAbs_VERTEX ) - { - SMESHDS_SubMesh* smDS = sm.GetSubMeshDS(); - if ( !smDS || !smDS->NbNodes() ) { - TopoDS_Vertex V = TopoDS::Vertex(sm.GetSubShape()); - gp_Pnt P = BRep_Tool::Pnt(V); - SMESHDS_Mesh * meshDS = sm.GetFather()->GetMeshDS(); - if ( SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z()) ) - meshDS->SetNodeOnVertex(node, V); - } - } - return sm.ComputeStateEngine(SMESH_subMesh::COMPUTE); -} - //============================================================================= /*! - * + * Compute a mesh */ //============================================================================= bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) { MESSAGE("SMESH_Gen::Compute"); - // bool isDone = false; - /* - Algo : s'appuie ou non sur une geometrie - Si geometrie: - Vertex : rien à faire (range le point) - Edge, Wire, collection d'edge et wire : 1D - Face, Shell, collection de Face et Shells : 2D - Solid, Collection de Solid : 3D - */ - // *** corriger commentaires - // check hypothesis associated to the mesh : - // - only one algo : type compatible with the type of the shape - // - hypothesis = compatible with algo - // - check if hypothesis are applicable to this algo - // - check contradictions within hypothesis - // (test if enough hypothesis is done further) bool ret = true; -// if ( !CheckAlgoState( aMesh, aShape )) -// { -// INFOS( "ABORT MESHING: some algos or hypothesis are missing"); -// return false; -// } - SMESH_subMesh *sm = aMesh.GetSubMesh(aShape); -// if ( sm->GetComputeState() == SMESH_subMesh::COMPUTE_OK ) -// return true; // already computed - // ----------------------------------------------------------------- // apply algos that do not require descretized boundaries, starting // from the most complex shapes // ----------------------------------------------------------------- - // map containing all subshapes in the order: vertices, edges, faces... - const map& smMap = sm->DependsOn(); - map::const_reverse_iterator revItSub = smMap.rbegin(); + const bool includeSelf = true; + const bool complexShapeFirst = true; - SMESH_subMesh* smToCompute = sm; - while ( smToCompute ) + SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(includeSelf, + complexShapeFirst); + while ( smIt->more() ) { + SMESH_subMesh* smToCompute = smIt->next(); + const TopoDS_Shape& aSubShape = smToCompute->GetSubShape(); if ( GetShapeDim( aSubShape ) < 1 ) break; SMESH_Algo* algo = GetAlgo( aMesh, aSubShape ); - if (algo && !algo->NeedDescretBoundary()) { - if (smToCompute->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE) { - ret = smToCompute->ComputeStateEngine( SMESH_subMesh::COMPUTE ); - } else if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE) { - // JFA for PAL6524 - ret = false; - } else { - } - } - if (!ret) - return false; - - // next subMesh - if (revItSub != smMap.rend()) + if (algo && !algo->NeedDescretBoundary()) { - smToCompute = (*revItSub).second; - revItSub++; + if (smToCompute->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE) + smToCompute->ComputeStateEngine( SMESH_subMesh::COMPUTE ); + + if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE) + ret = false;; } - else - smToCompute = 0; } // ----------------------------------------------- // mesh the rest subshapes starting from vertices // ----------------------------------------------- - - int i, nbSub = smMap.size(); - map::const_iterator itSub = smMap.begin(); - for ( i = 0; i <= nbSub; ++i ) // loop on the whole map plus + smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst); + while ( smIt->more() ) { - if ( itSub == smMap.end() ) - smToCompute = sm; - else - smToCompute = (itSub++)->second; + SMESH_subMesh* smToCompute = smIt->next(); - if (smToCompute->GetComputeState() != SMESH_subMesh::READY_TO_COMPUTE) { - if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE) - ret = false; - } - else if ( !Compute( *smToCompute )) { + if (smToCompute->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE) + smToCompute->ComputeStateEngine( SMESH_subMesh::COMPUTE ); + + if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE) ret = false; - } } MESSAGE( "VSR - SMESH_Gen::Compute() finished, OK = " << ret); return ret; } - //======================================================================= //function : checkConformIgnoredAlgos //purpose : @@ -311,7 +244,7 @@ static bool checkConformIgnoredAlgos(SMESH_Mesh& aMesh, "> would produce not conform mesh: " " hypotesis is missing"); theErrors.push_back( SMESH_Gen::TAlgoStateError() ); - theErrors.back().Set( SMESH_Gen::NOT_CONFORM_MESH, algo, false ); + theErrors.back().Set( SMESH_Hypothesis::HYP_NOTCONFORM, algo, false ); } // sub-algos will be hidden by a local @@ -371,7 +304,7 @@ static bool checkMissing(SMESH_Gen* aGen, INFOS( "ERROR: " << shapeDim << "D algorithm is missing" ); ret = false; theErrors.push_back( SMESH_Gen::TAlgoStateError() ); - theErrors.back().Set( SMESH_Gen::MISSING_ALGO, shapeDim, true ); + theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, shapeDim, true ); } } return ret; @@ -383,13 +316,13 @@ static bool checkMissing(SMESH_Gen* aGen, bool IsGlobalHypothesis = aGen->IsGlobalHypothesis( algo, aMesh ); if (!IsGlobalHypothesis || !globalChecked[ algo->GetDim() ]) { - SMESH_Gen::TAlgoStateErrorName errName = SMESH_Gen::MISSING_HYPO; + TAlgoStateErrorName errName = SMESH_Hypothesis::HYP_MISSING; SMESH_Hypothesis::Hypothesis_Status status; algo->CheckHypothesis( aMesh, aSubMesh->GetSubShape(), status ); if ( status == SMESH_Hypothesis::HYP_BAD_PARAMETER ) { INFOS( "ERROR: hypothesis of " << (IsGlobalHypothesis ? "Global " : "Local ") << "<" << algo->GetName() << "> has a bad parameter value"); - errName = SMESH_Gen::BAD_PARAM_VALUE; + errName = SMESH_Hypothesis::HYP_BAD_PARAMETER; } else { INFOS( "ERROR: " << (IsGlobalHypothesis ? "Global " : "Local ") << "<" << algo->GetName() << "> misses some hypothesis"); @@ -607,7 +540,7 @@ bool SMESH_Gen::GetAlgoState(SMESH_Mesh& theMesh, ret = false; INFOS( "None algorithm attached" ); theErrors.push_back( TAlgoStateError() ); - theErrors.back().Set( MISSING_ALGO, 1, true ); + theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, 1, true ); } return ret; diff --git a/src/SMESH/SMESH_Gen.hxx b/src/SMESH/SMESH_Gen.hxx index e3a59ef7d..e354d7e5d 100644 --- a/src/SMESH/SMESH_Gen.hxx +++ b/src/SMESH/SMESH_Gen.hxx @@ -32,6 +32,7 @@ #include "Utils_SALOME_Exception.hxx" #include "SMESH_Hypothesis.hxx" +#include "SMESH_ComputeError.hxx" #include "SMESH_Algo.hxx" #include "SMESH_0D_Algo.hxx" #include "SMESH_1D_Algo.hxx" @@ -45,6 +46,7 @@ #include +typedef SMESH_Hypothesis::Hypothesis_Status TAlgoStateErrorName; typedef struct studyContextStruct { @@ -59,23 +61,16 @@ class SMESH_Gen SMESH_Gen(); ~SMESH_Gen(); -// SMESH_Hypothesis *CreateHypothesis(const char *anHyp, int studyId) -// throw(SALOME_Exception); SMESH_Mesh* CreateMesh(int theStudyId, bool theIsEmbeddedMode) throw(SALOME_Exception); + bool Compute(::SMESH_Mesh & aMesh, const TopoDS_Shape & aShape); - bool Compute(::SMESH_subMesh& aSubMesh); bool CheckAlgoState(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); // notify on bad state of attached algos, return false // if Compute() would fail because of some algo bad state - enum TAlgoStateErrorName { NONE=0, - MISSING_ALGO, - MISSING_HYPO, - NOT_CONFORM_MESH, - BAD_PARAM_VALUE }; struct TAlgoStateError { TAlgoStateErrorName _name; @@ -83,7 +78,7 @@ class SMESH_Gen int _algoDim; bool _isGlobalAlgo; - TAlgoStateError(): _algoDim(0),_algo(0),_name(NONE) {} + TAlgoStateError(): _algoDim(0),_algo(0),_name(SMESH_Hypothesis::HYP_OK) {} void Set(TAlgoStateErrorName name, const SMESH_Algo* algo, bool isGlobal) { _name = name; _algo = algo; _algoDim = algo->GetDim(); _isGlobalAlgo = isGlobal; } void Set(TAlgoStateErrorName name, const int algoDim, bool isGlobal) @@ -96,7 +91,6 @@ class SMESH_Gen // if Compute() would fail because of some algo bad state // theErrors list contains problems description - StudyContextStruct *GetStudyContext(int studyId); static int GetShapeDim(const TopAbs_ShapeEnum & aShapeType); diff --git a/src/SMESH/SMESH_Hypothesis.hxx b/src/SMESH/SMESH_Hypothesis.hxx index 1b7146371..802d47e58 100644 --- a/src/SMESH/SMESH_Hypothesis.hxx +++ b/src/SMESH/SMESH_Hypothesis.hxx @@ -40,7 +40,7 @@ class SMESH_Hypothesis: public SMESHDS_Hypothesis public: enum Hypothesis_Status // in the order of severity { - HYP_OK, + HYP_OK = 0, HYP_MISSING, // algo misses a hypothesis HYP_CONCURENT, // several applicable hypotheses HYP_BAD_PARAMETER,// hypothesis has a bad parameter value diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index 67dc0a6bd..cc5da1dd7 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -414,11 +414,11 @@ SMESH_Hypothesis::Hypothesis_Status // check concurent hypotheses on ansestors if (ret < SMESH_Hypothesis::HYP_CONCURENT && !isGlobalHyp ) { - const map < int, SMESH_subMesh * >& smMap = subMesh->DependsOn(); - map < int, SMESH_subMesh * >::const_iterator smIt = smMap.begin(); - for ( ; smIt != smMap.end(); smIt++ ) { - if ( smIt->second->IsApplicableHypotesis( anHyp )) { - ret2 = smIt->second->CheckConcurentHypothesis( anHyp->GetType() ); + SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false); + while ( smIt->more() ) { + SMESH_subMesh* sm = smIt->next(); + if ( sm->IsApplicableHypotesis( anHyp )) { + ret2 = sm->CheckConcurentHypothesis( anHyp->GetType() ); if (ret2 > ret) { ret = ret2; break; @@ -504,11 +504,11 @@ SMESH_Hypothesis::Hypothesis_Status // check concurent hypotheses on ansestors if (ret < SMESH_Hypothesis::HYP_CONCURENT && !IsMainShape( aSubShape ) ) { - const map < int, SMESH_subMesh * >& smMap = subMesh->DependsOn(); - map < int, SMESH_subMesh * >::const_iterator smIt = smMap.begin(); - for ( ; smIt != smMap.end(); smIt++ ) { - if ( smIt->second->IsApplicableHypotesis( anHyp )) { - ret2 = smIt->second->CheckConcurentHypothesis( anHyp->GetType() ); + SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false); + while ( smIt->more() ) { + SMESH_subMesh* sm = smIt->next(); + if ( sm->IsApplicableHypotesis( anHyp )) { + ret2 = sm->CheckConcurentHypothesis( anHyp->GetType() ); if (ret2 > ret) { ret = ret2; break; @@ -815,12 +815,10 @@ SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp) //purpose : Say all submeshes using theChangedHyp that it has been modified //======================================================================= -void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* theChangedHyp) +void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* hyp) { Unexpect aCatch(SalomeException); - const SMESH_Hypothesis* hyp = cSMESH_Hyp(theChangedHyp); - const SMESH_Algo *foundAlgo = 0; SMESH_HypoFilter algoKind( SMESH_HypoFilter::IsAlgo() ); SMESH_HypoFilter compatibleHypoKind; diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 8fce57fbf..615d5bbbc 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -28,13 +28,15 @@ #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" @@ -72,7 +74,6 @@ SMESH_subMesh::SMESH_subMesh(int Id, const TopoDS_Shape & aSubShape) { _subShape = aSubShape; - _meshDS = meshDS; _subMeshDS = meshDS->MeshElements(_subShape); // may be null ... _father = father; _Id = Id; @@ -124,7 +125,7 @@ int SMESH_subMesh::GetId() const 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 } //============================================================================= @@ -135,9 +136,10 @@ SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS() 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(); } @@ -149,27 +151,11 @@ SMESHDS_SubMesh* SMESH_subMesh::CreateSubMeshDS() 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 } @@ -202,6 +188,7 @@ bool SMESH_subMesh::IsMeshComputed() const // 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++) { @@ -210,9 +197,12 @@ bool SMESH_subMesh::IsMeshComputed() const 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 @@ -230,17 +220,14 @@ bool SMESH_subMesh::IsMeshComputed() const 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(); @@ -317,16 +304,12 @@ bool SMESH_subMesh::SubMeshesComputed() 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; @@ -349,7 +332,7 @@ bool SMESH_subMesh::SubMeshesReady() */ //============================================================================= -const map < int, SMESH_subMesh * >&SMESH_subMesh::DependsOn() +const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() { if (_dependenceAnalysed) return _mapDepend; @@ -567,8 +550,9 @@ SMESH_Hypothesis::Hypothesis_Status 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 ) { @@ -621,7 +605,7 @@ SMESH_Hypothesis::Hypothesis_Status 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 @@ -673,7 +657,7 @@ SMESH_Hypothesis::Hypothesis_Status // -------------------------- 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 @@ -750,7 +734,7 @@ SMESH_Hypothesis::Hypothesis_Status 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 @@ -803,10 +787,10 @@ SMESH_Hypothesis::Hypothesis_Status 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; @@ -817,7 +801,7 @@ SMESH_Hypothesis::Hypothesis_Status 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 @@ -905,7 +889,7 @@ SMESH_Hypothesis::Hypothesis_Status if (SMESH_Hypothesis::IsStatusFatal( ret )) { MESSAGE("do not add extra hypothesis"); - _meshDS->RemoveHypothesis(_subShape, anHyp); + meshDS->RemoveHypothesis(_subShape, anHyp); } else { @@ -1151,20 +1135,15 @@ SMESH_Hypothesis::Hypothesis_Status 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 { - 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; } @@ -1180,15 +1159,9 @@ SMESH_Hypothesis::Hypothesis_Status 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); } //============================================================================= @@ -1267,8 +1240,10 @@ static void cleanSubMesh( SMESH_subMesh * subMesh ) while (itn->more()) { const SMDS_MeshNode * node = itn->next(); //MESSAGE( " RM 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); } } } @@ -1282,16 +1257,27 @@ static void cleanSubMesh( SMESH_subMesh * subMesh ) 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; @@ -1369,69 +1355,87 @@ bool SMESH_subMesh::ComputeStateEngine(int event) 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 : + ( _father->IsNotConformAllowed() || !subComputed )); + if (!ret) { + _computeState = FAILED_TO_COMPUTE; + if ( !algo->NeedDescretBoundary() ) + _computeError = + SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH,"Unexpected submesh",algo); + break; + } } // compute CleanDependants(); RemoveSubMeshElementsAndNodes(); - { - try { + ret = false; + _computeState = FAILED_TO_COMPUTE; + _computeError = SMESH_ComputeError::New(COMPERR_EXCEPTION,"",algo); + 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(); + if ( !_father->HasShapeToMesh() ) // no shape + { + SMESH_MesherHelper helper( *_father ); + helper.SetSubShape( _subShape ); + helper.SetElementsOnShape( true ); + ret = algo->Compute(*_father, &helper ); } - catch (Standard_Failure) { - MESSAGE( "Exception in algo->Compute() "); - ret = false; - } - } + else + { + if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput()) + ret = ApplyToCollection( algo, GetCollection( gen, algo ) ); + else + ret = algo->Compute((*_father), _subShape); + } + _computeError = algo->GetComputeError(); + } + catch (Standard_Failure& exc) { + if ( !_computeError ) _computeError = SMESH_ComputeError::New(); + _computeError->myName = COMPERR_OCC_EXCEPTION; + _computeError->myComment = exc.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; + _computeError->myComment = exc.what(); + } + if ( ret && _computeError && !_computeError->IsOK() ) { + ret = false; + } + if (ret) { // check if anything was built + ret = ( GetSubMeshDS() && ( GetSubMeshDS()->NbElements() || GetSubMeshDS()->NbNodes() )); + } if (!ret) { - MESSAGE("problem in algo execution: failed to compute"); - // release ALGO from responsibilty of partially built mesh - RemoveSubMeshElementsAndNodes(); - _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; + // Set _computeError + if ( !_computeError ) + _computeError = SMESH_ComputeError::New(); + if ( _computeError->IsOK() ) + _computeError->myName = COMPERR_ALGO_FAILED; } else { - _computeState = COMPUTE_OK; + _computeError.reset(); UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED - if (!algo->NeedDescretBoundary()) - UpdateSubMeshState( COMPUTE_OK ); } + CheckComputeError( algo ); } break; case CLEAN: @@ -1532,10 +1536,6 @@ bool SMESH_subMesh::ComputeStateEngine(int event) 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) @@ -1574,6 +1574,59 @@ bool SMESH_subMesh::ComputeStateEngine(int event) return ret; } +//======================================================================= +/*! + * \brief Update compute_state by _computeError + */ +//======================================================================= + +bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo) +{ + bool noErrors = ( !_computeError || _computeError->IsOK() ); + if ( !noErrors ) + { + 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; + } +#else + 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; + } + return noErrors; +} + //======================================================================= //function : ApplyToCollection //purpose : Apply theAlgo to all subshapes in theCollection @@ -1585,32 +1638,26 @@ bool SMESH_subMesh::ApplyToCollection (SMESH_Algo* theAlgo, 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 + bool localOK = true; 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 - { - subMesh->_computeState = FAILED_TO_COMPUTE; - } + if ( !subMesh->CheckComputeError( theAlgo )) + localOK = false; } } - return ret; + if ( !ok && localOK ) + return false; // store error in this subMesh + + return ( this->_computeState == COMPUTE_OK ); } @@ -1621,13 +1668,9 @@ bool SMESH_subMesh::ApplyToCollection (SMESH_Algo* theAlgo, void SMESH_subMesh::UpdateSubMeshState(const compute_state theState) { - const map& smMap = DependsOn(); - map::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; } //======================================================================= @@ -1637,13 +1680,9 @@ void SMESH_subMesh::UpdateSubMeshState(const compute_state theState) void SMESH_subMesh::ComputeSubMeshStateEngine(int event) { - const map& smMap = DependsOn(); - map::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); } //======================================================================= @@ -1752,14 +1791,17 @@ TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlg { 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; @@ -1969,7 +2011,7 @@ void SMESH_subMeshEventListener::ProcessEvent(const int event, 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) @@ -1987,3 +2029,69 @@ void SMESH_subMeshEventListener::ProcessEvent(const int event, } } } + +namespace { + + //================================================================================ + /*! + * \brief Iterator over submeshes and optionally prepended or appended one + */ + //================================================================================ + + struct _Iterator : public SMDS_Iterator + { + _Iterator(SMDS_Iterator* 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 *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( DependsOn() ), prepend, append )); + } + { + return SMESH_subMeshIteratorPtr + ( new _Iterator( new SMDS_mapIterator( DependsOn() ), prepend, append )); + } +} diff --git a/src/SMESH/SMESH_subMesh.hxx b/src/SMESH/SMESH_subMesh.hxx index 801fd77b5..8481f3b0e 100644 --- a/src/SMESH/SMESH_subMesh.hxx +++ b/src/SMESH/SMESH_subMesh.hxx @@ -32,12 +32,12 @@ #include "SMESHDS_Mesh.hxx" #include "SMESHDS_SubMesh.hxx" #include "SMESH_Hypothesis.hxx" +#include "SMESH_ComputeError.hxx" + #include "Utils_SALOME_Exception.hxx" + #include -#include -#include -#include #include #include @@ -47,10 +47,14 @@ class SMESH_Algo; class SMESH_Gen; class SMESH_subMeshEventListener; class SMESH_subMeshEventListenerData; +class SMESH_subMesh; typedef SMESH_subMeshEventListener EventListener; typedef SMESH_subMeshEventListenerData EventListenerData; +typedef boost::shared_ptr< SMDS_Iterator > SMESH_subMeshIteratorPtr; + + class SMESH_subMesh { public: @@ -60,9 +64,6 @@ class SMESH_subMesh int GetId() const; - // bool Contains(const TopoDS_Shape & aSubShape) - // throw (SALOME_Exception); - SMESH_Mesh* GetFather() { return _father; } SMESHDS_SubMesh * GetSubMeshDS(); @@ -72,8 +73,13 @@ class SMESH_subMesh SMESH_subMesh *GetFirstToCompute(); - const map < int, SMESH_subMesh * >&DependsOn(); + const map < int, SMESH_subMesh * >& DependsOn(); //const map < int, SMESH_subMesh * >&Dependants(); + /*! + * \brief Return iterator on the submeshes this one depends on + */ + SMESH_subMeshIteratorPtr getDependsOnIterator(const bool includeSelf, + const bool complexShapeFirst); const TopoDS_Shape & GetSubShape() const; @@ -179,6 +185,7 @@ public: int GetAlgoState() const { return _algoState; } int GetComputeState() const { return _computeState; }; + SMESH_ComputeErrorPtr& GetComputeError() { return _computeError; } void DumpAlgoState(bool isMain); @@ -211,6 +218,7 @@ public: */ void SetIsAlwaysComputed(bool isAlCo); + protected: // ================================================================== void InsertDependence(const TopoDS_Shape aSubShape); @@ -227,38 +235,54 @@ protected: void CleanDependsOn(); void SetAlgoState(int state); + /*! + * \brief Return a shape containing all sub-shapes of the MainShape that can be + * meshed at once along with _subShape + */ TopoDS_Shape GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo); - // return a shape containing all sub-shapes of the MainShape that can be - // meshed at once along with _subShape + /*! + * \brief Apply theAlgo to all subshapes in theCollection + */ bool ApplyToCollection (SMESH_Algo* theAlgo, const TopoDS_Shape& theCollection); - // Apply theAlgo to all subshapes in theCollection + /*! + * \brief Update compute_state by _computeError + * \retval bool - false if there are errors + */ + bool CheckComputeError(SMESH_Algo* theAlgo); + + /*! + * \brief Return a hypothesis attached to theShape. + * + * If theHyp is provided, similar but not same hypotheses + * is returned; else an applicable ones having theHypType + * is returned + */ const SMESH_Hypothesis* GetSimilarAttached(const TopoDS_Shape& theShape, const SMESH_Hypothesis * theHyp, const int theHypType = 0); - // return a hypothesis attached to theShape. - // If theHyp is provided, similar but not same hypotheses - // is returned; else an applicable ones having theHypType - // is returned - + // + +protected: + + TopoDS_Shape _subShape; + SMESHDS_SubMesh * _subMeshDS; + SMESH_Mesh * _father; + int _Id; - TopoDS_Shape _subShape; - SMESHDS_Mesh * _meshDS; - SMESHDS_SubMesh * _subMeshDS; - int _Id; - SMESH_Mesh *_father; map < int, SMESH_subMesh * >_mapDepend; - bool _dependenceAnalysed; + bool _dependenceAnalysed; - int _algoState; - int _computeState; + int _algoState; + int _computeState; + SMESH_ComputeErrorPtr _computeError; // allow algo->Compute() if a subshape of lower dim is meshed but // none mesh entity is bound to it. Eg StdMeshers_CompositeSegment_1D can // mesh several edges as a whole and leave some of them without mesh entities - bool _alwaysComputed; + bool _alwaysComputed; }; diff --git a/src/SMESH/SMESH_subMeshEventListener.hxx b/src/SMESH/SMESH_subMeshEventListener.hxx index 2424bfe54..227bf5ebf 100644 --- a/src/SMESH/SMESH_subMeshEventListener.hxx +++ b/src/SMESH/SMESH_subMeshEventListener.hxx @@ -62,7 +62,7 @@ public: const int eventType, SMESH_subMesh* subMesh, SMESH_subMeshEventListenerData* data, - SMESH_Hypothesis* hyp = 0); + const SMESH_Hypothesis* hyp = 0); }; // ------------------------------------------------------------------