X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_subMesh.cxx;h=19f10229a442b7929e16a2c930e80312d21541e1;hp=8c2702a47b3e9121c6fdac9c43333ed5434be5a9;hb=81bd0885814f1219569c20815ebcaf7346705dbc;hpb=897fdb92b6c3bd5cfc749bde222355992ecffc13 diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 8c2702a47..19f10229a 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2015 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 @@ -27,16 +27,16 @@ #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 @@ -241,7 +241,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(); @@ -280,7 +280,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() ) { @@ -291,67 +291,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; } @@ -403,13 +358,7 @@ int SMESH_subMesh::computeCost() const //============================================================================= /*! - * 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 */ //============================================================================= @@ -444,7 +393,8 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() } break; case TopAbs_COMPSOLID: insertDependence( _subShape, TopAbs_SOLID ); break; - case TopAbs_SOLID: insertDependence( _subShape, TopAbs_FACE ); 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; @@ -461,30 +411,37 @@ 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 aShape, - TopAbs_ShapeEnum aSubType) + TopAbs_ShapeEnum aSubType, + TopAbs_ShapeEnum avoidType) { - TopExp_Explorer sub( aShape, aSubType ); + TopExp_Explorer sub( aShape, aSubType, avoidType ); for ( ; sub.More(); sub.Next() ) { 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()) { @@ -506,6 +463,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 @@ -596,13 +564,14 @@ bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis, //================================================================================ 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; @@ -892,7 +861,7 @@ SMESH_Hypothesis::Hypothesis_Status f.AndNot( SMESH_HypoFilter::Is( algo )); 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 @@ -1009,8 +978,8 @@ 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? @@ -1095,8 +1064,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() ) @@ -1155,7 +1122,7 @@ void SMESH_subMesh::setAlgoState(algo_state state) //================================================================================ SMESH_Hypothesis::Hypothesis_Status - SMESH_subMesh::SubMeshesAlgoStateEngine(int event, + SMESH_subMesh::SubMeshesAlgoStateEngine(algo_event event, SMESH_Hypothesis * anHyp, bool exitOnFatal) { @@ -1205,8 +1172,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; @@ -1218,30 +1183,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() ); } @@ -1304,24 +1272,44 @@ 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); + int nbElems = subMeshDS->NbElements(); + if ( nbElems > 0 ) + { + // start from elem with max ID to avoid filling the pool of IDs + bool rev = true; + SMDS_ElemIteratorPtr ite = subMeshDS->GetElements( rev ); + const SMDS_MeshElement * lastElem = ite->next(); + rev = ( lastElem->GetID() == meshDS->MaxElementID() ); + if ( !rev ) + ite = subMeshDS->GetElements( rev ); + else + meshDS->RemoveFreeElement( lastElem, subMeshDS ); + while (ite->more()) { + const SMDS_MeshElement * elt = ite->next(); + meshDS->RemoveFreeElement( elt, subMeshDS ); + } } - - 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 nbNodes = subMeshDS->NbNodes(); + if ( nbNodes > 0 ) + { + bool rev = true; + SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes( rev ); + const SMDS_MeshNode * lastNode = itn->next(); + rev = ( lastNode->GetID() == meshDS->MaxNodeID() ); + if ( !rev ) + itn = subMeshDS->GetNodes( rev ); + else + meshDS->RemoveNode( lastNode ); + while (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(); } @@ -1334,7 +1322,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: @@ -1531,7 +1519,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; @@ -1540,7 +1527,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(); @@ -1581,7 +1567,7 @@ 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()) if ( !_father->GetSubMesh( subS.Current() )->IsMeshComputed() && @@ -1590,9 +1576,9 @@ bool SMESH_subMesh::ComputeStateEngine(int event) ret = false; } // 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() ) @@ -1606,11 +1592,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() ) @@ -1824,12 +1840,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; @@ -1847,8 +1863,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))); } @@ -1956,7 +1987,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() ) @@ -2066,10 +2097,10 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, const TopoDS_Shape& S = subMesh->_subShape; if ( S.ShapeType() != this->_subShape.ShapeType() ) continue; - theSubs.push_back( subMesh ); if ( subMesh == this ) { aBuilder.Add( aCompound, S ); + theSubs.push_back( subMesh ); } else if ( subMesh->GetComputeState() == READY_TO_COMPUTE ) { @@ -2080,6 +2111,7 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, aBuilder.Add( aCompound, S ); if ( !subMesh->SubMeshesComputed() ) theSubComputed = false; + theSubs.push_back( subMesh ); } } } @@ -2427,7 +2459,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: @@ -2452,7 +2484,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; @@ -2557,7 +2589,7 @@ void SMESH_subMesh::ClearAncestors() 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();