X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_subMesh.cxx;h=5b5de318b6a1d46e29ff7f5990f9e62222989fef;hp=67649a3265de416d0d4204e5d4e8cb1e41af6c11;hb=2f529dcd2629679dadcca3047583bfcf28ca7b1a;hpb=c81123c27bc5f59480e785631bc3bd338ce4074c diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 67649a326..5b5de318b 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,25 +20,23 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// SMESH SMESH : implementaion of SMESH idl descriptions +// SMESH SMESH : implementation of SMESH idl descriptions // File : SMESH_subMesh.cxx // Author : Paul RASCLE, EDF // Module : SMESH #include "SMESH_subMesh.hxx" +#include "SMDS_SetIterator.hxx" +#include "SMESHDS_Mesh.hxx" #include "SMESH_Algo.hxx" +#include "SMESH_Comment.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 "SMDSAbs_ElementType.hxx" - -#include #include "utilities.h" #include "OpUtil.hxx" @@ -47,13 +45,14 @@ #include #include #include +#include #include #include +#include #include #include -#include -#include #include +#include #include #include @@ -62,6 +61,11 @@ using namespace std; +#ifdef _DEBUG_ +// enable printing algo + shape id + hypo used while meshing +//#define PRINT_WHO_COMPUTE_WHAT +#endif + //============================================================================= /*! * \brief Allocate some memory at construction and release it at destruction. @@ -116,8 +120,6 @@ SMESH_subMesh::SMESH_subMesh(int Id, SMESH_subMesh::~SMESH_subMesh() { - MESSAGE("SMESH_subMesh::~SMESH_subMesh"); - // **** deleteOwnListeners(); } @@ -197,7 +199,10 @@ SMESH_subMesh *SMESH_subMesh::GetFirstToCompute() SMESH_Algo* SMESH_subMesh::GetAlgo() const { if ( !_algo ) - ((SMESH_subMesh*)this)->_algo = _father->GetGen()->GetAlgo(*_father, _subShape); + { + SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this ); + me->_algo = _father->GetGen()->GetAlgo( me ); + } return _algo; } @@ -239,7 +244,7 @@ bool SMESH_subMesh::IsMeshComputed() const { if ( _alwaysComputed ) return true; - // algo may bind a submesh not to _subShape, eg 3D algo + // algo may bind a sub-mesh not to _subShape, eg 3D algo // sets nodes on SHELL while _subShape may be SOLID SMESHDS_Mesh* meshDS = _father->GetMeshDS(); @@ -278,7 +283,7 @@ bool SMESH_subMesh::SubMeshesComputed(bool * isFailedToCompute/*=0*/) const int dimToCheck = myDim - 1; bool subMeshesComputed = true; if ( isFailedToCompute ) *isFailedToCompute = false; - // check subMeshes with upper dimension => reverse iteration + // check sub-meshes with upper dimension => reverse iteration SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true); while ( smIt->more() ) { @@ -289,67 +294,22 @@ bool SMESH_subMesh::SubMeshesComputed(bool * isFailedToCompute/*=0*/) const // MSV 07.04.2006: restrict checking to myDim-1 only. Ex., there is no sense // in checking of existence of edges if the algo needs only faces. Moreover, - // degenerated edges may have no submesh, as after computing NETGEN_2D. + // degenerated edges may have no sub-mesh, as after computing NETGEN_2D. if ( !_algo || _algo->NeedDiscreteBoundary() ) { int dim = SMESH_Gen::GetShapeDim( ss ); if (dim < dimToCheck) - break; // the rest subMeshes are all of less dimension + break; // the rest sub-meshes are all of less dimension } SMESHDS_SubMesh * ds = sm->GetSubMeshDS(); - bool computeOk = (sm->GetComputeState() == COMPUTE_OK || - (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes() ))); + bool computeOk = ((sm->GetComputeState() == COMPUTE_OK ) || + (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes() ))); if (!computeOk) { subMeshesComputed = false; + if ( isFailedToCompute && !(*isFailedToCompute) ) *isFailedToCompute = ( sm->GetComputeState() == FAILED_TO_COMPUTE ); - // int type = ss.ShapeType(); - - // switch (type) - // { - // case TopAbs_COMPOUND: - // { - // MESSAGE("The not computed sub mesh is a COMPOUND"); - // break; - // } - // case TopAbs_COMPSOLID: - // { - // MESSAGE("The not computed sub mesh is a COMPSOLID"); - // break; - // } - // case TopAbs_SHELL: - // { - // MESSAGE("The not computed sub mesh is a SHEL"); - // break; - // } - // case TopAbs_WIRE: - // { - // MESSAGE("The not computed sub mesh is a WIRE"); - // break; - // } - // case TopAbs_SOLID: - // { - // MESSAGE("The not computed sub mesh is a SOLID"); - // break; - // } - // case TopAbs_FACE: - // { - // MESSAGE("The not computed sub mesh is a FACE"); - // break; - // } - // case TopAbs_EDGE: - // { - // MESSAGE("The not computed sub mesh is a EDGE"); - // break; - // } - // default: - // { - // MESSAGE("The not computed sub mesh is of unknown type"); - // break; - // } - // } - if ( !isFailedToCompute ) break; } @@ -401,146 +361,49 @@ int SMESH_subMesh::computeCost() const //============================================================================= /*! - * - */ -//============================================================================= - -// bool SMESH_subMesh::SubMeshesReady() -// { -// bool subMeshesReady = true; -// 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; -// SCRUTE(sm->GetId()); -// break; -// } -// } -// return subMeshesReady; -// } - -//============================================================================= -/*! - * Construct dependence on first level subMeshes. complex shapes (compsolid, - * shell, wire) are not analysed the same way as simple shapes (solid, face, - * edge). - * For collection shapes (compsolid, shell, wire) prepare a list of submeshes - * with possible multiples occurences. Multiples occurences corresponds to - * internal frontiers within shapes of the collection and must not be keeped. - * See FinalizeDependence. + * Returns all sub-meshes this one depend on */ //============================================================================= const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() { - if (_dependenceAnalysed) + if ( _dependenceAnalysed || !_father->HasShapeToMesh() ) return _mapDepend; - //MESSAGE("SMESH_subMesh::DependsOn"); - int type = _subShape.ShapeType(); - //SCRUTE(type); switch (type) { case TopAbs_COMPOUND: + { + list< TopoDS_Shape > compounds( 1, _subShape ); + list< TopoDS_Shape >::iterator comp = compounds.begin(); + for ( ; comp != compounds.end(); ++comp ) { - //MESSAGE("compound"); - for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();exp.Next()) - { - insertDependence(exp.Current()); - } - for (TopExp_Explorer exp(_subShape, TopAbs_SHELL, TopAbs_SOLID); exp.More(); exp.Next()) - { - if ( BRep_Tool::IsClosed(exp.Current() )) - insertDependence(exp.Current()); //only shell not in solid - else - for (TopExp_Explorer expF(exp.Current(), TopAbs_FACE); expF.More();expF.Next()) - insertDependence(expF.Current()); // issue 0020959: HEXA_3D fails on shell - - } - for (TopExp_Explorer exp(_subShape, TopAbs_FACE, TopAbs_SHELL); exp.More();exp.Next()) - { - insertDependence(exp.Current()); - } - for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();exp.Next()) - { - insertDependence(exp.Current()); - } - for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX, TopAbs_EDGE); exp.More();exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_COMPSOLID: - { - //MESSAGE("compsolid"); - for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More(); exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_SHELL: - { - //MESSAGE("shell"); - for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More(); exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_WIRE: - { - //MESSAGE("wire"); - for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More(); exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_SOLID: - { - //MESSAGE("solid"); - if(_father->HasShapeToMesh()) { - for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();exp.Next()) + for ( TopoDS_Iterator sub( *comp ); sub.More(); sub.Next() ) + switch ( sub.Value().ShapeType() ) { - insertDependence(exp.Current()); + case TopAbs_COMPOUND: compounds.push_back( sub.Value() ); break; + case TopAbs_COMPSOLID: insertDependence( sub.Value(), TopAbs_SOLID ); break; + case TopAbs_SOLID: insertDependence( sub.Value(), TopAbs_SOLID ); break; + case TopAbs_SHELL: insertDependence( sub.Value(), TopAbs_FACE ); break; + case TopAbs_FACE: insertDependence( sub.Value(), TopAbs_FACE ); break; + case TopAbs_WIRE: insertDependence( sub.Value(), TopAbs_EDGE ); break; + case TopAbs_EDGE: insertDependence( sub.Value(), TopAbs_EDGE ); break; + case TopAbs_VERTEX: insertDependence( sub.Value(), TopAbs_VERTEX ); break; + default:; } - } - break; - } - case TopAbs_FACE: - { - //MESSAGE("face"); - for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_EDGE: - { - //MESSAGE("edge"); - for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More(); exp.Next()) - { - insertDependence(exp.Current()); - } - break; - } - case TopAbs_VERTEX: - { - break; - } - default: - { - break; } } + break; + case TopAbs_COMPSOLID: insertDependence( _subShape, TopAbs_SOLID ); break; + case TopAbs_SOLID: insertDependence( _subShape, TopAbs_FACE ); + { /*internal EDGE*/ insertDependence( _subShape, TopAbs_EDGE, TopAbs_WIRE ); break; } + case TopAbs_SHELL: insertDependence( _subShape, TopAbs_FACE ); break; + case TopAbs_FACE: insertDependence( _subShape, TopAbs_EDGE ); break; + case TopAbs_WIRE: insertDependence( _subShape, TopAbs_EDGE ); break; + case TopAbs_EDGE: insertDependence( _subShape, TopAbs_VERTEX ); break; + default:; + } _dependenceAnalysed = true; return _mapDepend; } @@ -551,32 +414,44 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() */ //================================================================================ -namespace { - int dependsOnMapKey( const SMESH_subMesh* sm ) +namespace +{ + int dependsOnMapKey( TopAbs_ShapeEnum type, int shapeID ) { - int type = sm->GetSubShape().ShapeType(); - int ordType = 9 - type; // 2 = Vertex, 8 = CompSolid - int cle = sm->GetId(); + int ordType = 9 - int(type); // 2 = Vertex, 8 = CompSolid + int cle = shapeID; cle += 10000000 * ordType; // sort map by ordType then index return cle; } + int dependsOnMapKey( const SMESH_subMesh* sm ) + { + return dependsOnMapKey( sm->GetSubShape().ShapeType(), sm->GetId() ); + } } //============================================================================= /*! - * For simple Shapes (solid, face, edge): add subMesh into dependence list. + * Add sub-meshes on sub-shapes of a given type into the dependence map. */ //============================================================================= -void SMESH_subMesh::insertDependence(const TopoDS_Shape aSubShape) +void SMESH_subMesh::insertDependence(const TopoDS_Shape aShape, + TopAbs_ShapeEnum aSubType, + TopAbs_ShapeEnum avoidType) { - SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape); - int cle = dependsOnMapKey( aSubMesh ); - if ( _mapDepend.find( cle ) == _mapDepend.end()) + TopExp_Explorer sub( aShape, aSubType, avoidType ); + for ( ; sub.More(); sub.Next() ) { - _mapDepend[cle] = aSubMesh; - const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn(); - _mapDepend.insert( subMap.begin(), subMap.end() ); + SMESH_subMesh *aSubMesh = _father->GetSubMesh( sub.Current() ); + if ( aSubMesh->GetId() == 0 ) + continue; // not a sub-shape of the shape to mesh + int cle = dependsOnMapKey( aSubMesh ); + if ( _mapDepend.find( cle ) == _mapDepend.end()) + { + _mapDepend[cle] = aSubMesh; + const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn(); + _mapDepend.insert( subMap.begin(), subMap.end() ); + } } } @@ -591,6 +466,17 @@ bool SMESH_subMesh::DependsOn( const SMESH_subMesh* other ) const return other ? _mapDepend.count( dependsOnMapKey( other )) : false; } +//================================================================================ +/*! + * \brief Return \c true if \a this sub-mesh depends on a \a shape + */ +//================================================================================ + +bool SMESH_subMesh::DependsOn( const int shapeID ) const +{ + return DependsOn( _father->GetSubMeshContaining( shapeID )); +} + //============================================================================= /*! * Return a shape of \a this sub-mesh @@ -605,7 +491,7 @@ const TopoDS_Shape & SMESH_subMesh::GetSubShape() const //======================================================================= //function : CanAddHypothesis //purpose : return true if theHypothesis can be attached to me: -// its dimention is checked +// its dimension is checked //======================================================================= bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) const @@ -626,12 +512,25 @@ bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) cons } //======================================================================= -//function : IsApplicableHypotesis -//purpose : +//function : IsApplicableHypothesis +//purpose : check if this sub-mesh can be computed using a hypothesis +//======================================================================= + +bool SMESH_subMesh::IsApplicableHypothesis(const SMESH_Hypothesis* theHypothesis) const +{ + if ( !_father->HasShapeToMesh() && _subShape.ShapeType() == TopAbs_SOLID ) + return true; // true for the PseudoShape + + return IsApplicableHypothesis( theHypothesis, _subShape.ShapeType() ); +} + +//======================================================================= +//function : IsApplicableHypothesis +//purpose : compare shape type and hypothesis type //======================================================================= -bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis, - const TopAbs_ShapeEnum theShapeType) +bool SMESH_subMesh::IsApplicableHypothesis(const SMESH_Hypothesis* theHypothesis, + const TopAbs_ShapeEnum theShapeType) { if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO) { @@ -668,20 +567,27 @@ bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis, return false; } -//============================================================================= +//================================================================================ /*! - * + * \brief Treats modification of hypotheses definition + * \param [in] event - what happens + * \param [in] anHyp - a hypothesis + * \return SMESH_Hypothesis::Hypothesis_Status - a treatment result. + * + * Optional description of a problematic situation (if any) can be retrieved + * via GetComputeError(). */ -//============================================================================= +//================================================================================ SMESH_Hypothesis::Hypothesis_Status - SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp) + SMESH_subMesh::AlgoStateEngine(algo_event event, SMESH_Hypothesis * anHyp) { // **** les retour des evenement shape sont significatifs // (add ou remove fait ou non) // le retour des evenement father n'indiquent pas que add ou remove fait SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK; + if ( _Id == 0 ) return ret; // not a sub-shape of the shape to mesh SMESHDS_Mesh* meshDS =_father->GetMeshDS(); SMESH_Algo* algo = 0; @@ -716,7 +622,7 @@ SMESH_Hypothesis::Hypothesis_Status bool modifiedHyp = (event == MODIF_HYP); // if set to true, force event MODIF_ALGO_STATE SMESH_Algo* algoRequiringCleaning = 0; - bool isApplicableHyp = IsApplicableHypotesis( anHyp ); + bool isApplicableHyp = IsApplicableHypothesis( anHyp ); if (event == ADD_ALGO || event == ADD_FATHER_ALGO) { @@ -737,8 +643,8 @@ SMESH_Hypothesis::Hypothesis_Status SMESH_HypoFilter filter( SMESH_HypoFilter::HasType( algo->GetType() )); filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+1 )); filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+2 )); - if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis(_subShape, filter, true )) - if ( !curAlgo->NeedDiscreteBoundary() ) + if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis( this, filter, true )) + if ( !curAlgo->NeedDiscreteBoundary() && curAlgo != anHyp ) algoRequiringCleaning = curAlgo; } } @@ -751,7 +657,7 @@ SMESH_Hypothesis::Hypothesis_Status if ( ! CanAddHypothesis( anHyp )) // check dimension return SMESH_Hypothesis::HYP_BAD_DIM; - if ( /*!anHyp->IsAuxiliary() &&*/ getSimilarAttached( _subShape, anHyp ) ) + if ( !anHyp->IsAuxiliary() && getSimilarAttached( _subShape, anHyp ) ) return SMESH_Hypothesis::HYP_ALREADY_EXIST; if ( !meshDS->AddHypothesis(_subShape, anHyp)) @@ -780,6 +686,9 @@ SMESH_Hypothesis::Hypothesis_Status if (!isApplicableHyp) return ret; // not applicable hypotheses do not change algo state + if (( algo = GetAlgo())) + algo->InitComputeError(); + switch (_algoState) { @@ -944,7 +853,7 @@ SMESH_Hypothesis::Hypothesis_Status // ret should be fatal: anHyp was not added ret = SMESH_Hypothesis::HYP_INCOMPATIBLE; } - else if (!_father->IsUsedHypothesis( anHyp, this )) + else if (!_father->IsUsedHypothesis( anHyp, this )) ret = SMESH_Hypothesis::HYP_INCOMPATIBLE; if (SMESH_Hypothesis::IsStatusFatal( ret )) @@ -966,9 +875,9 @@ SMESH_Hypothesis::Hypothesis_Status f.Init( SMESH_HypoFilter::IsAlgo() ); f.And( SMESH_HypoFilter::IsApplicableTo( _subShape )); f.AndNot( SMESH_HypoFilter::Is( algo )); - const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true ); + const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( this, f, true ); if (prevAlgo && - string(algo->GetName()) != string(prevAlgo->GetName()) ) + string( algo->GetName()) != prevAlgo->GetName()) modifiedHyp = true; } else @@ -1025,7 +934,7 @@ SMESH_Hypothesis::Hypothesis_Status f.Init( SMESH_HypoFilter::IsAlgo() ); f.And( SMESH_HypoFilter::IsApplicableTo( _subShape )); f.AndNot( SMESH_HypoFilter::Is( algo )); - const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true ); + const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( this, f, true ); if (prevAlgo && string(algo->GetName()) != string(prevAlgo->GetName()) ) modifiedHyp = true; @@ -1085,32 +994,38 @@ SMESH_Hypothesis::Hypothesis_Status // detect algorithm hiding // - if ( ret == SMESH_Hypothesis::HYP_OK && - ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) && + if ( ret == SMESH_Hypothesis::HYP_OK && + ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) && algo && algo->GetName() == anHyp->GetName() ) { // is algo hidden? SMESH_Gen* gen = _father->GetGen(); - TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape )); - for ( ; ( ret == SMESH_Hypothesis::HYP_OK && it.More()); it.Next() ) { - if ( SMESH_Algo* upperAlgo = gen->GetAlgo( *_father, it.Value() )) + const std::vector< SMESH_subMesh * > & ancestors = GetAncestors(); + for ( size_t iA = 0; ( ret == SMESH_Hypothesis::HYP_OK && iA < ancestors.size()); ++iA ) { + if ( SMESH_Algo* upperAlgo = ancestors[ iA ]->GetAlgo() ) if ( !upperAlgo->NeedDiscreteBoundary() && !upperAlgo->SupportSubmeshes()) ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO; } // is algo hiding? if ( ret == SMESH_Hypothesis::HYP_OK && !algo->NeedDiscreteBoundary() && - !algo->SupportSubmeshes()) { + !algo->SupportSubmeshes()) + { TopoDS_Shape algoAssignedTo, otherAssignedTo; - gen->GetAlgo( *_father, _subShape, &algoAssignedTo ); + gen->GetAlgo( this, &algoAssignedTo ); map::reverse_iterator i_sm = _mapDepend.rbegin(); for ( ; ( ret == SMESH_Hypothesis::HYP_OK && i_sm != _mapDepend.rend()) ; ++i_sm ) - if ( gen->GetAlgo( *_father, i_sm->second->_subShape, &otherAssignedTo ) && + if ( gen->GetAlgo( i_sm->second, &otherAssignedTo ) && SMESH_MesherHelper::IsSubShape( /*sub=*/otherAssignedTo, /*main=*/algoAssignedTo )) ret = SMESH_Hypothesis::HYP_HIDING_ALGO; } } + if ( _algo ) { // get an error description set by _algo->CheckHypothesis() + _computeError = _algo->GetComputeError(); + _algo->InitComputeError(); + } + bool stateChange = ( _algoState != oldAlgoState ); if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK @@ -1138,8 +1053,8 @@ SMESH_Hypothesis::Hypothesis_Status ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE ); } - if (stateChange || modifiedHyp) - ComputeStateEngine(MODIF_ALGO_STATE); + if ( stateChange || modifiedHyp ) + ComputeStateEngine( MODIF_ALGO_STATE ); _realComputeCost = ( _algoState == HYP_OK ) ? computeCost() : 0; @@ -1157,7 +1072,7 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo) if ( !theAlgo ) return false; // Suppose that theAlgo is applicable to _subShape, do not check it here - //if ( !IsApplicableHypotesis( theAlgo )) return false; + //if ( !IsApplicableHypothesis( theAlgo )) return false; // check only algo that doesn't NeedDiscreteBoundary(): because mesh made // on a sub-shape will be ignored by theAlgo @@ -1165,8 +1080,6 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo) !theAlgo->OnlyUnaryInput() ) // all adjacent shapes will be meshed by this algo? return true; - SMESH_Gen* gen =_father->GetGen(); - // only local algo is to be checked //if ( gen->IsGlobalHypothesis( theAlgo, *_father )) if ( _subShape.ShapeType() == _father->GetMeshDS()->ShapeToMesh().ShapeType() ) @@ -1179,16 +1092,16 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo) for (; itsub.More(); itsub.Next()) { // loop on adjacent subShapes - TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( itsub.Value() )); - for (; it.More(); it.Next()) + const std::vector< SMESH_subMesh * > & ancestors = GetAncestors(); + for ( size_t iA = 0; iA < ancestors.size(); ++iA ) { - const TopoDS_Shape& adjacent = it.Value(); + const TopoDS_Shape& adjacent = ancestors[ iA ]->GetSubShape(); if ( _subShape.IsSame( adjacent )) continue; if ( adjacent.ShapeType() != _subShape.ShapeType()) break; // check algo attached to smAdjacent - SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent); + SMESH_Algo * algo = ancestors[ iA ]->GetAlgo(); if (algo && !algo->NeedDiscreteBoundary() && algo->OnlyUnaryInput()) @@ -1210,14 +1123,24 @@ void SMESH_subMesh::setAlgoState(algo_state state) _algoState = state; } -//============================================================================= +//================================================================================ /*! + * \brief Send an event to sub-meshes + * \param [in] event - the event + * \param [in] anHyp - an hypothesis + * \param [in] exitOnFatal - to stop iteration on sub-meshes if a sub-mesh + * reports a fatal result + * \return SMESH_Hypothesis::Hypothesis_Status - the worst result * + * Optional description of a problematic situation (if any) can be retrieved + * via GetComputeError(). */ -//============================================================================= +//================================================================================ + SMESH_Hypothesis::Hypothesis_Status - SMESH_subMesh::SubMeshesAlgoStateEngine(int event, - SMESH_Hypothesis * anHyp) + SMESH_subMesh::SubMeshesAlgoStateEngine(algo_event event, + SMESH_Hypothesis * anHyp, + bool exitOnFatal) { SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK; //EAP: a wire (dim==1) should notify edges (dim==1) @@ -1226,10 +1149,16 @@ SMESH_Hypothesis::Hypothesis_Status { SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); while ( smIt->more() ) { - SMESH_Hypothesis::Hypothesis_Status ret2 = - smIt->next()->AlgoStateEngine(event, anHyp); + SMESH_subMesh* sm = smIt->next(); + SMESH_Hypothesis::Hypothesis_Status ret2 = sm->AlgoStateEngine(event, anHyp); if ( ret2 > ret ) + { ret = ret2; + _computeError = sm->_computeError; + sm->_computeError.reset(); + if ( exitOnFatal && SMESH_Hypothesis::IsStatusFatal( ret )) + break; + } } } return ret; @@ -1259,8 +1188,6 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ ) } else if ( algoRequiringCleaning && algoRequiringCleaning->SupportSubmeshes() ) { - SMESHDS_Mesh* meshDS = _father->GetMeshDS(); - // find sub-meshes to keep elements on set< SMESH_subMesh* > smToKeep; TopAbs_ShapeEnum prevShapeType = TopAbs_SHAPE; @@ -1272,30 +1199,33 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ ) if ( !sm->IsEmpty() ) { const bool sameShapeType = ( prevShapeType == sm->GetSubShape().ShapeType() ); - bool keepSubMeshes = ( sameShapeType && toKeepPrevShapeType ); + bool keepSubMeshes = ( sameShapeType && toKeepPrevShapeType ); if ( !sameShapeType ) { // check if the algo allows presence of global algos of dimension the algo - // can generate it-self + // can generate it-self; + // always keep a node on VERTEX, as this node can be shared by segments + // lying on EDGEs not shared by the VERTEX of sm, due to MergeNodes (PAL23068) int shapeDim = SMESH_Gen::GetShapeDim( sm->GetSubShape() ); - keepSubMeshes = algoRequiringCleaning->NeedLowerHyps( shapeDim ); + keepSubMeshes = ( algoRequiringCleaning->NeedLowerHyps( shapeDim ) || shapeDim == 0 ); prevShapeType = sm->GetSubShape().ShapeType(); toKeepPrevShapeType = keepSubMeshes; } if ( !keepSubMeshes ) { - // look for an algo assigned to sm - bool algoFound = false; - const list& hyps = meshDS->GetHypothesis( sm->_subShape ); - list::const_iterator h = hyps.begin(); - for ( ; ( !algoFound && h != hyps.end() ); ++h ) - algoFound = ((*h)->GetType() != SMESHDS_Hypothesis::PARAM_ALGO ); - keepSubMeshes = algoFound; + // look for a local algo used to mesh sm + TopoDS_Shape algoShape = SMESH_MesherHelper::GetShapeOfHypothesis + ( algoRequiringCleaning, _subShape, _father ); + SMESH_HypoFilter moreLocalAlgo; + moreLocalAlgo.Init( SMESH_HypoFilter::IsMoreLocalThan( algoShape, *_father )); + moreLocalAlgo.And ( SMESH_HypoFilter::IsAlgo() ); + bool localAlgoFound = _father->GetHypothesis( sm->_subShape, moreLocalAlgo, true ); + keepSubMeshes = localAlgoFound; } // remember all sub-meshes of sm if ( keepSubMeshes ) { - SMESH_subMeshIteratorPtr smIt2 = getDependsOnIterator(false,true); + SMESH_subMeshIteratorPtr smIt2 = sm->getDependsOnIterator(true); while ( smIt2->more() ) smToKeep.insert( smIt2->next() ); } @@ -1320,48 +1250,32 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ ) void SMESH_subMesh::DumpAlgoState(bool isMain) { - // if (dim < 1) return; - if (isMain) - { - const map < int, SMESH_subMesh * >&subMeshes = DependsOn(); + if (isMain) + { + 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; - sm->DumpAlgoState(false); - } - } - //int type = _subShape.ShapeType(); - MESSAGE("dim = " << SMESH_Gen::GetShapeDim(_subShape) << - " type of shape " << _subShape.ShapeType()); - switch (_algoState) - { - case NO_ALGO: - MESSAGE(" AlgoState = NO_ALGO"); - break; - case MISSING_HYP: - MESSAGE(" AlgoState = MISSING_HYP"); - break; - case HYP_OK: - MESSAGE(" AlgoState = HYP_OK"); - break; - } - switch (_computeState) - { - case NOT_READY: - MESSAGE(" ComputeState = NOT_READY"); - break; - case READY_TO_COMPUTE: - MESSAGE(" ComputeState = READY_TO_COMPUTE"); - break; - case COMPUTE_OK: - MESSAGE(" ComputeState = COMPUTE_OK"); - break; - case FAILED_TO_COMPUTE: - MESSAGE(" ComputeState = FAILED_TO_COMPUTE"); - break; - } + map < int, SMESH_subMesh * >::const_iterator itsub; + for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++) + { + SMESH_subMesh *sm = (*itsub).second; + sm->DumpAlgoState(false); + } + } + MESSAGE("dim = " << SMESH_Gen::GetShapeDim(_subShape) << + " type of shape " << _subShape.ShapeType()); + switch (_algoState) + { + case NO_ALGO : MESSAGE(" AlgoState = NO_ALGO"); break; + case MISSING_HYP : MESSAGE(" AlgoState = MISSING_HYP"); break; + case HYP_OK : MESSAGE(" AlgoState = HYP_OK");break; + } + switch (_computeState) + { + case NOT_READY : MESSAGE(" ComputeState = NOT_READY");break; + case READY_TO_COMPUTE : MESSAGE(" ComputeState = READY_TO_COMPUTE");break; + case COMPUTE_OK : MESSAGE(" ComputeState = COMPUTE_OK");break; + case FAILED_TO_COMPUTE: MESSAGE(" ComputeState = FAILED_TO_COMPUTE");break; + } } //================================================================================ @@ -1374,25 +1288,24 @@ void SMESH_subMesh::DumpAlgoState(bool isMain) static void cleanSubMesh( SMESH_subMesh * subMesh ) { if (subMesh) { - if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS()) { + if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS()) + { SMESHDS_Mesh * meshDS = subMesh->GetFather()->GetMeshDS(); - SMDS_ElemIteratorPtr ite = subMeshDS->GetElements(); - while (ite->more()) { - const SMDS_MeshElement * elt = ite->next(); - //MESSAGE( " RM elt: "<GetID()<<" ( "<NbNodes()<<" )" ); - //meshDS->RemoveElement(elt); - meshDS->RemoveFreeElement(elt, 0); - } - - SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes(); - while (itn->more()) { - const SMDS_MeshNode * node = itn->next(); - //MESSAGE( " RM node: "<GetID()); - if ( node->NbInverseElements() == 0 ) - meshDS->RemoveFreeNode(node, 0); - else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another - meshDS->RemoveNode(node); - } + int nbElems = subMeshDS->NbElements(); + if ( nbElems > 0 ) + for ( SMDS_ElemIteratorPtr ite = subMeshDS->GetElements(); ite->more(); ) + meshDS->RemoveFreeElement( ite->next(), subMeshDS ); + + int nbNodes = subMeshDS->NbNodes(); + if ( nbNodes > 0 ) + for ( SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes(); itn->more() ; ) + { + const SMDS_MeshNode * node = itn->next(); + if ( node->NbInverseElements() == 0 ) + meshDS->RemoveFreeNode( node, subMeshDS ); + else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another + meshDS->RemoveNode( node ); + } subMeshDS->Clear(); } } @@ -1404,7 +1317,7 @@ static void cleanSubMesh( SMESH_subMesh * subMesh ) */ //============================================================================= -bool SMESH_subMesh::ComputeStateEngine(int event) +bool SMESH_subMesh::ComputeStateEngine(compute_event event) { switch ( event ) { case MODIF_ALGO_STATE: @@ -1518,6 +1431,31 @@ bool SMESH_subMesh::ComputeStateEngine(int event) _computeState = READY_TO_COMPUTE; } break; + + case COMPUTE_NOGEOM: // no geometry; can be several algos + if ( !_father->HasShapeToMesh() ) + { + algo = GetAlgo(); // current algo + if ( algo ) + { + // apply algos in the order of increasing dimension + std::list< const SMESHDS_Hypothesis * > algos = _father->GetHypothesisList( _subShape ); + for ( int t = SMESHDS_Hypothesis::ALGO_1D; t <= SMESHDS_Hypothesis::ALGO_3D; ++t ) + { + std::list::iterator al = algos.begin(); + for ( ; al != algos.end(); ++al ) + if ( (*al)->GetType() == t ) + { + _algo = (SMESH_Algo*) *al; + _computeState = READY_TO_COMPUTE; + if ( !ComputeStateEngine( COMPUTE )) + break; + } + } + _algo = algo; // restore + } + break; + } case COMPUTE: case COMPUTE_SUBMESH: { @@ -1555,7 +1493,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event) if ( !algo->NeedDiscreteBoundary() && !subFailed ) _computeError = SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH, - "Unexpected computed submesh",algo); + "Unexpected computed sub-mesh",algo); break; // goto exit } } @@ -1571,9 +1509,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) _computeState = FAILED_TO_COMPUTE; _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo); try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif + algo->InitComputeError(); MemoryReserve aMemoryReserve; @@ -1590,8 +1527,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) { ret = algo->Compute((*_father), shape); } - if ( !_computeError || (/* !ret && */_computeError->IsOK() ) ) // algo can set _computeError of submesh - _computeError = algo->GetComputeError(); + // algo can set _computeError of submesh + _computeError = SMESH_ComputeError::Worst( _computeError, algo->GetComputeError() ); } catch ( ::SMESH_ComputeError& comperr ) { cout << " SMESH_ComputeError caught" << endl; @@ -1602,7 +1539,6 @@ bool SMESH_subMesh::ComputeStateEngine(int event) MESSAGE("std::bad_alloc thrown inside algo->Compute()"); if ( _computeError ) { _computeError->myName = COMPERR_MEMORY_PB; - //_computeError->myComment = exc.what(); } cleanSubMesh( this ); throw exc; @@ -1611,7 +1547,6 @@ bool SMESH_subMesh::ComputeStateEngine(int event) MESSAGE("Standard_OutOfMemory thrown inside algo->Compute()"); if ( _computeError ) { _computeError->myName = COMPERR_MEMORY_PB; - //_computeError->myComment = exc.what(); } cleanSubMesh( this ); throw std::bad_alloc(); @@ -1652,15 +1587,35 @@ bool SMESH_subMesh::ComputeStateEngine(int event) ret = false; // check if anything was built TopExp_Explorer subS(shape, _subShape.ShapeType()); - if (ret) + if ( ret ) { for (; ret && subS.More(); subS.Next()) - ret = _father->GetSubMesh( subS.Current() )->IsMeshComputed(); + if ( !_father->GetSubMesh( subS.Current() )->IsMeshComputed() && + ( _subShape.ShapeType() != TopAbs_EDGE || + !algo->isDegenerated( TopoDS::Edge( subS.Current() )))) + ret = false; + } +#ifdef PRINT_WHO_COMPUTE_WHAT + for (subS.ReInit(); subS.More(); subS.Next()) + { + const std::list & hyps = + _algo->GetUsedHypothesis( *_father, _subShape ); + SMESH_Comment hypStr; + if ( !hyps.empty() ) + { + hypStr << hyps.front()->GetName() << " "; + ((SMESHDS_Hypothesis*)hyps.front())->SaveTo( hypStr.Stream() ); + hypStr << " "; + } + cout << _algo->GetName() + << " " << _father->GetSubMesh( subS.Current() )->GetId() + << " " << hypStr << endl; } +#endif // Set _computeError - if (!ret && !isComputeErrorSet) + if ( !ret && !isComputeErrorSet ) { - for (subS.ReInit(); subS.More(); subS.Next()) + for ( subS.ReInit(); subS.More(); subS.Next() ) { SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() ); if ( !sm->IsMeshComputed() ) @@ -1674,11 +1629,41 @@ bool SMESH_subMesh::ComputeStateEngine(int event) } } } - if (ret && _computeError && _computeError->myName != COMPERR_WARNING ) + if ( ret && _computeError && _computeError->myName != COMPERR_WARNING ) { _computeError.reset(); } + // transform errors into warnings if it is caused by mesh edition (imp 0023068) + if (!ret && _father->GetIsModified() ) + { + for (subS.ReInit(); subS.More(); subS.Next()) + { + SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() ); + if ( !sm->IsMeshComputed() && sm->_computeError ) + { + // check if there is a VERTEX w/o nodes + // with READY_TO_COMPUTE state (after MergeNodes()) + SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,false); + while ( smIt->more() ) + { + SMESH_subMesh * vertSM = smIt->next(); + if ( vertSM->_subShape.ShapeType() != TopAbs_VERTEX ) break; + if ( vertSM->GetComputeState() == READY_TO_COMPUTE ) + { + SMESHDS_SubMesh * ds = vertSM->GetSubMeshDS(); + if ( !ds || ds->NbNodes() == 0 ) + { + sm->_computeState = READY_TO_COMPUTE; + sm->_computeError->myName = COMPERR_WARNING; + break; + } + } + } + } + } + } + // send event SUBMESH_COMPUTED if ( ret ) { if ( !algo->NeedDiscreteBoundary() ) @@ -1735,6 +1720,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) case CHECK_COMPUTE_STATE: if ( IsMeshComputed() ) _computeState = COMPUTE_OK; + else if ( _computeError && _computeError->IsKO() ) + _computeState = FAILED_TO_COMPUTE; break; default: ASSERT(0); @@ -1758,7 +1745,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event) case COMPUTE_CANCELED: // nothing to do break; case CLEAN: - cleanDependants(); // clean sub-meshes, dependant on this one, with event CLEAN + cleanDependants(); // clean sub-meshes, dependent on this one, with event CLEAN removeSubMeshElementsAndNodes(); _computeState = NOT_READY; if ( _algoState == HYP_OK ) @@ -1824,10 +1811,13 @@ bool SMESH_subMesh::ComputeStateEngine(int event) removeSubMeshElementsAndNodes(); break; case SUBMESH_COMPUTED: // allow retry compute - if (_algoState == HYP_OK) - _computeState = READY_TO_COMPUTE; - else - _computeState = NOT_READY; + if ( IsEmpty() ) // 23061 + { + if (_algoState == HYP_OK) + _computeState = READY_TO_COMPUTE; + else + _computeState = NOT_READY; + } break; case SUBMESH_RESTORED: ComputeSubMeshStateEngine( SUBMESH_RESTORED ); @@ -1887,12 +1877,12 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap) SMESH_Hypothesis::Hypothesis_Status hyp_status; algo = GetAlgo(); - if(algo && !aResMap.count(this) ) + if( algo && !aResMap.count( this )) { ret = algo->CheckHypothesis((*_father), _subShape, hyp_status); if (!ret) return false; - if (_father->HasShapeToMesh() && algo->NeedDiscreteBoundary()) + if (_father->HasShapeToMesh() && algo->NeedDiscreteBoundary() ) { // check submeshes needed bool subMeshEvaluated = true; @@ -1910,8 +1900,23 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap) return false; } _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo); - ret = algo->Evaluate((*_father), _subShape, aResMap); + if ( IsMeshComputed() ) + { + vector & nbEntities = aResMap[ this ]; + nbEntities.resize( SMDSEntity_Last, 0 ); + if ( SMESHDS_SubMesh* sm = GetSubMeshDS() ) + { + nbEntities[ SMDSEntity_Node ] = sm->NbNodes(); + SMDS_ElemIteratorPtr elemIt = sm->GetElements(); + while ( elemIt->more() ) + nbEntities[ elemIt->next()->GetEntityType() ]++; + } + } + else + { + ret = algo->Evaluate((*_father), _subShape, aResMap); + } aResMap.insert( make_pair( this,vector(0))); } @@ -2019,7 +2024,7 @@ void SMESH_subMesh::updateSubMeshState(const compute_state theState) //purpose : //======================================================================= -void SMESH_subMesh::ComputeSubMeshStateEngine(int event, const bool includeSelf) +void SMESH_subMesh::ComputeSubMeshStateEngine(compute_event event, const bool includeSelf) { SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(includeSelf,false); while ( smIt->more() ) @@ -2033,47 +2038,41 @@ void SMESH_subMesh::ComputeSubMeshStateEngine(int event, const bool includeSelf) void SMESH_subMesh::updateDependantsState(const compute_event theEvent) { - TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape )); - for (; it.More(); it.Next()) + const std::vector< SMESH_subMesh * > & ancestors = GetAncestors(); + for ( size_t iA = 0; iA < ancestors.size(); ++iA ) { - const TopoDS_Shape& ancestor = it.Value(); - if ( SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor)) - aSubMesh->ComputeStateEngine( theEvent ); + ancestors[ iA ]->ComputeStateEngine( theEvent ); } } -//============================================================================= -/*! - * - */ -//============================================================================= +//======================================================================= +//function : cleanDependants +//purpose : +//======================================================================= void SMESH_subMesh::cleanDependants() { int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1; - TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape )); - for (; it.More(); it.Next()) + const std::vector< SMESH_subMesh * > & ancestors = GetAncestors(); + for ( size_t iA = 0; iA < ancestors.size(); ++iA ) { - const TopoDS_Shape& ancestor = it.Value(); - if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) { + const TopoDS_Shape& ancestor = ancestors[ iA ]->GetSubShape(); + if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) + { // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEAN) // will erase mesh on other shapes in a compound - if ( ancestor.ShapeType() >= TopAbs_SOLID ) { - SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor); - if (aSubMesh && - !aSubMesh->IsEmpty() ) // prevent infinite CLEAN via event lesteners - aSubMesh->ComputeStateEngine(CLEAN); - } + if ( ancestor.ShapeType() >= TopAbs_SOLID && + !ancestors[ iA ]->IsEmpty() ) // prevent infinite CLEAN via event lesteners + ancestors[ iA ]->ComputeStateEngine(CLEAN); } } } -//============================================================================= -/*! - * - */ -//============================================================================= +//======================================================================= +//function : removeSubMeshElementsAndNodes +//purpose : +//======================================================================= void SMESH_subMesh::removeSubMeshElementsAndNodes() { @@ -2115,12 +2114,12 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, if ( mainShape.IsSame( _subShape )) return _subShape; - const bool ignoreAuxiliaryHyps = false; + const bool skipAuxHyps = false; list aUsedHyp = - theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy + theAlgo->GetUsedHypothesis( *_father, _subShape, skipAuxHyps ); // copy // put in a compound all shapes with the same hypothesis assigned - // and a good ComputState + // and a good ComputeState TopoDS_Compound aCompound; BRep_Builder aBuilder; @@ -2128,24 +2127,29 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, theSubs.clear(); - TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() ); - for ( ; anExplorer.More(); anExplorer.Next() ) + SMESH_subMeshIteratorPtr smIt = _father->GetSubMesh( mainShape )->getDependsOnIterator(false); + while ( smIt->more() ) { - const TopoDS_Shape& S = anExplorer.Current(); - SMESH_subMesh* subMesh = _father->GetSubMesh( S ); - theSubs.push_back( subMesh ); + SMESH_subMesh* subMesh = smIt->next(); + const TopoDS_Shape& S = subMesh->_subShape; + if ( S.ShapeType() != this->_subShape.ShapeType() ) + continue; if ( subMesh == this ) { aBuilder.Add( aCompound, S ); + theSubs.push_back( subMesh ); } else if ( subMesh->GetComputeState() == READY_TO_COMPUTE ) { - SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S ); - if (strcmp( anAlgo->GetName(), theAlgo->GetName()) == 0 && // same algo - anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) // same hyps + SMESH_Algo* anAlgo = subMesh->GetAlgo(); + if (( anAlgo->IsSameName( *theAlgo )) && // same algo + ( anAlgo->GetUsedHypothesis( *_father, S, skipAuxHyps ) == aUsedHyp )) // same hyps + { aBuilder.Add( aCompound, S ); - if ( !subMesh->SubMeshesComputed() ) - theSubComputed = false; + if ( !subMesh->SubMeshesComputed() ) + theSubComputed = false; + theSubs.push_back( subMesh ); + } } } @@ -2182,16 +2186,14 @@ const SMESH_Hypothesis* SMESH_subMesh::getSimilarAttached(const TopoDS_Shape& } //======================================================================= -//function : CheckConcurentHypothesis +//function : CheckConcurrentHypothesis //purpose : check if there are several applicable hypothesis attached to // ancestors //======================================================================= SMESH_Hypothesis::Hypothesis_Status - SMESH_subMesh::CheckConcurentHypothesis (const int theHypType) + SMESH_subMesh::CheckConcurrentHypothesis (const int theHypType) { - MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis"); - // is there local hypothesis on me? if ( getSimilarAttached( _subShape, 0, theHypType ) ) return SMESH_Hypothesis::HYP_OK; @@ -2212,7 +2214,7 @@ SMESH_Hypothesis::Hypothesis_Status aPrevHyp = hyp; } else if ( aPrevWithHyp.ShapeType() == ancestor.ShapeType() && aPrevHyp != hyp ) - return SMESH_Hypothesis::HYP_CONCURENT; + return SMESH_Hypothesis::HYP_CONCURRENT; else return SMESH_Hypothesis::HYP_OK; } @@ -2274,9 +2276,9 @@ void SMESH_subMesh::setEventListener(EventListener* listener, _eventListeners.find( listener ); if ( l_d != _eventListeners.end() ) { EventListenerData* curData = l_d->second; + l_d->second = data; if ( curData && curData != data && curData->IsDeletable() ) delete curData; - l_d->second = data; } else { @@ -2284,9 +2286,10 @@ void SMESH_subMesh::setEventListener(EventListener* listener, if ( listener->GetName() == l_d->first->GetName() ) { EventListenerData* curData = l_d->second; + l_d->second = 0; if ( curData && curData != data && curData->IsDeletable() ) delete curData; - if ( l_d->first->IsDeletable() ) + if ( l_d->first != listener && l_d->first->IsDeletable() ) delete l_d->first; _eventListeners.erase( l_d ); break; @@ -2299,16 +2302,31 @@ void SMESH_subMesh::setEventListener(EventListener* listener, /*! * \brief Return an event listener data * \param listener - the listener whose data is + * \param myOwn - if \c true, returns a listener set by this sub-mesh, + * else returns a listener listening to events of this sub-mesh * \retval EventListenerData* - found data, maybe NULL */ //================================================================================ -EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) const +EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener, + const bool myOwn) const { - map< EventListener*, EventListenerData* >::const_iterator l_d = - _eventListeners.find( listener ); - if ( l_d != _eventListeners.end() ) - return l_d->second; + if ( myOwn ) + { + list< OwnListenerData >::const_iterator d; + for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d ) + { + if ( d->myListener == listener && _father->MeshExists( d->myMeshID )) + return d->mySubMesh->GetEventListenerData( listener, !myOwn ); + } + } + else + { + map< EventListener*, EventListenerData* >::const_iterator l_d = + _eventListeners.find( listener ); + if ( l_d != _eventListeners.end() ) + return l_d->second; + } return 0; } @@ -2316,22 +2334,37 @@ EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) /*! * \brief Return an event listener data * \param listenerName - the listener name + * \param myOwn - if \c true, returns a listener set by this sub-mesh, + * else returns a listener listening to events of this sub-mesh * \retval EventListenerData* - found data, maybe NULL */ //================================================================================ -EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerName) const +EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerName, + const bool myOwn) const { - map< EventListener*, EventListenerData* >::const_iterator l_d = _eventListeners.begin(); - for ( ; l_d != _eventListeners.end(); ++l_d ) - if ( listenerName == l_d->first->GetName() ) - return l_d->second; + if ( myOwn ) + { + list< OwnListenerData >::const_iterator d; + for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d ) + { + if ( _father->MeshExists( d->myMeshID ) && listenerName == d->myListener->GetName()) + return d->mySubMesh->GetEventListenerData( listenerName, !myOwn ); + } + } + else + { + map< EventListener*, EventListenerData* >::const_iterator l_d = _eventListeners.begin(); + for ( ; l_d != _eventListeners.end(); ++l_d ) + if ( listenerName == l_d->first->GetName() ) + return l_d->second; + } return 0; } //================================================================================ /*! - * \brief Notify stored event listeners on the occured event + * \brief Notify stored event listeners on the occurred event * \param event - algo_event or compute_event itself * \param eventType - algo_event or compute_event * \param hyp - hypothesis, if eventType is algo_event @@ -2400,9 +2433,8 @@ void SMESH_subMesh::deleteOwnListeners() list< OwnListenerData >::iterator d; for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d ) { - if ( !_father->MeshExists( d->myMeshID )) - continue; - if ( _father->GetId() == d->myMeshID && !_father->GetSubMeshContaining( d->mySubMeshID )) + SMESH_Mesh* mesh = _father->FindMesh( d->myMeshID ); + if ( !mesh || !mesh->GetSubMeshContaining( d->mySubMeshID )) continue; d->mySubMesh->DeleteEventListener( d->myListener ); } @@ -2438,7 +2470,7 @@ void SMESH_subMesh::loadDependentMeshes() * \brief Do something on a certain event * \param event - algo_event or compute_event itself * \param eventType - algo_event or compute_event - * \param subMesh - the submesh where the event occures + * \param subMesh - the submesh where the event occurs * \param data - listener data stored in the subMesh * \param hyp - hypothesis, if eventType is algo_event * @@ -2463,7 +2495,7 @@ void SMESH_subMeshEventListener::ProcessEvent(const int event, switch ( event ) { case SMESH_subMesh::CLEAN: for ( ; smIt != smEnd; ++ smIt) - (*smIt)->ComputeStateEngine( event ); + (*smIt)->ComputeStateEngine( SMESH_subMesh::compute_event( event )); break; case SMESH_subMesh::COMPUTE: case SMESH_subMesh::COMPUTE_SUBMESH: @@ -2488,7 +2520,7 @@ namespace { { _Iterator(SMDS_Iterator* subIt, SMESH_subMesh* prepend, - SMESH_subMesh* append): myIt(subIt),myAppend(append) + SMESH_subMesh* append): myAppend(append), myIt(subIt) { myCur = prepend ? prepend : myIt->more() ? myIt->next() : append; if ( myCur == append ) append = 0; @@ -2517,9 +2549,9 @@ namespace { //================================================================================ /*! - * \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 + * \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 */ //================================================================================ @@ -2544,6 +2576,47 @@ SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeS } } +//================================================================================ +/*! + * \brief Returns ancestor sub-meshes. Finds them if not yet found. + */ +//================================================================================ + +const std::vector< SMESH_subMesh * > & SMESH_subMesh::GetAncestors() const +{ + if ( _ancestors.empty() && + !_subShape.IsSame( _father->GetShapeToMesh() )) + { + const TopTools_ListOfShape& ancShapes = _father->GetAncestors( _subShape ); + + SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this ); + me->_ancestors.reserve( ancShapes.Extent() ); + + TopTools_MapOfShape map; + + // assure that all sub-meshes exist + _father->GetSubMesh( _father->GetShapeToMesh() )->DependsOn(); + + for ( TopTools_ListIteratorOfListOfShape it( ancShapes ); it.More(); it.Next() ) + if ( SMESH_subMesh* sm = _father->GetSubMeshContaining( it.Value() )) + if ( map.Add( it.Value() )) + me->_ancestors.push_back( sm ); + } + + return _ancestors; +} + +//================================================================================ +/*! + * \brief Clears the vector of ancestor sub-meshes + */ +//================================================================================ + +void SMESH_subMesh::ClearAncestors() +{ + _ancestors.clear(); +} + //================================================================================ /*! * \brief Find common submeshes (based on shared sub-shapes with other @@ -2552,16 +2625,18 @@ SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeS */ //================================================================================ -bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther, +bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther, std::set& theSetOfCommon ) const { - int oldNb = theSetOfCommon.size(); + size_t oldNb = theSetOfCommon.size(); + // check main submeshes const map ::const_iterator otherEnd = theOther->_mapDepend.end(); if ( theOther->_mapDepend.find(this->GetId()) != otherEnd ) theSetOfCommon.insert( this ); if ( _mapDepend.find(theOther->GetId()) != _mapDepend.end() ) theSetOfCommon.insert( theOther ); + // check common submeshes map ::const_iterator mapIt = _mapDepend.begin(); for( ; mapIt != _mapDepend.end(); mapIt++ )