diff --git a/doc/salome/gui/SMESH/images/split_into_tetra_icon.png b/doc/salome/gui/SMESH/images/split_into_tetra_icon.png index b113c304d..c9ea7b4c9 100644 Binary files a/doc/salome/gui/SMESH/images/split_into_tetra_icon.png and b/doc/salome/gui/SMESH/images/split_into_tetra_icon.png differ diff --git a/resources/split_into_tetra.png b/resources/split_into_tetra.png index b113c304d..c9ea7b4c9 100644 Binary files a/resources/split_into_tetra.png and b/resources/split_into_tetra.png differ diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 64ee5948d..19931be61 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -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; } @@ -1254,7 +1209,7 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ ) // remember all sub-meshes of sm if ( keepSubMeshes ) { - SMESH_subMeshIteratorPtr smIt2 = getDependsOnIterator(false); + SMESH_subMeshIteratorPtr smIt2 = sm->getDependsOnIterator(true); while ( smIt2->more() ) smToKeep.insert( smIt2->next() ); } @@ -1624,6 +1579,36 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) _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() ) diff --git a/src/SMESH/SMESH_subMesh.hxx b/src/SMESH/SMESH_subMesh.hxx index 331d70160..8de40d222 100644 --- a/src/SMESH/SMESH_subMesh.hxx +++ b/src/SMESH/SMESH_subMesh.hxx @@ -96,8 +96,7 @@ class SMESH_EXPORT SMESH_subMesh enum compute_state { - NOT_READY, READY_TO_COMPUTE, - COMPUTE_OK, FAILED_TO_COMPUTE + NOT_READY, READY_TO_COMPUTE, COMPUTE_OK, FAILED_TO_COMPUTE }; enum algo_state { @@ -123,7 +122,7 @@ class SMESH_EXPORT SMESH_subMesh }; // ================================================================== - // Members to track non hierarchical dependencies between submeshes + // Members to track non hierarchical dependencies between sub-meshes // ================================================================== /*! diff --git a/src/SMESH_I/SMESH_subMesh_i.cxx b/src/SMESH_I/SMESH_subMesh_i.cxx index 7f86e0ddc..a660013ed 100644 --- a/src/SMESH_I/SMESH_subMesh_i.cxx +++ b/src/SMESH_I/SMESH_subMesh_i.cxx @@ -29,14 +29,13 @@ #include "SMESH_Gen_i.hxx" #include "SMESH_Mesh_i.hxx" #include "SMESH_PreMeshInfo.hxx" +#include "SMESH_MesherHelper.hxx" #include "Utils_CorbaException.hxx" #include "utilities.h" #include "OpUtil.hxx" #include "Utils_ExceptHandlers.hxx" -#include -#include #include using namespace std; @@ -97,99 +96,37 @@ bool getSubMeshes(::SMESH_subMesh* theSubMesh, { size_t size = theSubMeshList.size(); - SMESH_Mesh* aMesh = theSubMesh->GetFather(); - SMESHDS_Mesh* aMeshDS = aMesh->GetMeshDS(); - SMESHDS_SubMesh* aSubMeshDS = theSubMesh->GetSubMeshDS(); - ::SMESH_subMesh* sm; + // check all child sub-meshes of one complexity, + // if no elements found and no algo assigned, go to children of lower complexity - // nodes can be bound to either vertex, edge, face or solid_or_shell - TopoDS_Shape aShape = theSubMesh->GetSubShape(); - TopAbs_ShapeEnum aShapeType = aShape.ShapeType(); - - // IPAL18558: Wrong information of the created sub-mesh is shown. (Sub-mesh on a FACE - // with only 1D algo assigned) - // Find dimension of sub-meshes to return as highest dimension of the assigned algorithm - if (( theSubMesh->IsEmpty() || ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() )) && - ( !theSubMesh->GetAlgo() )) + TopoDS_Shape shape = theSubMesh->GetSubShape(); + TopAbs_ShapeEnum mainType = SMESH_MesherHelper::GetGroupType( shape, /*noCompound=*/true ); + TopAbs_ShapeEnum shapeType = shape.ShapeType(); + bool elementsFound = false; + bool algoFound = false; + SMESH_subMeshIteratorPtr smIt = theSubMesh->getDependsOnIterator(/*includeSelf=*/true, + /*complexFirst=*/true); + while ( smIt->more() ) { - // on father sub-meshes, check presence of an algo which will mesh this sub-mesh - // even if no algo is assigned to this sub-mesh - bool topAlgoPresent = false; - TopTools_ListIteratorOfListOfShape ancestors( aMesh->GetAncestors( aShape )); - for ( ; ancestors.More() && !topAlgoPresent; ancestors.Next() ) - if (( sm = aMesh->GetSubMeshContaining( ancestors.Value() ))) - topAlgoPresent = ( sm->GetAlgo() && !sm->GetAlgo()->NeedDiscreteBoundary() ); - - if ( !topAlgoPresent ) + ::SMESH_subMesh* sm = smIt->next(); + if ( sm->GetSubShape().ShapeType() != shapeType ) { - // find max dimension of an assigned algo - TopAbs_ShapeEnum algoShape = TopAbs_SHAPE; - const std::list & hyps = aMesh->GetHypothesisList( aShape ); - std::list ::const_iterator hypIt = hyps.begin(); - for ( ; hypIt != hyps.end(); ++hypIt ) - if ( const SMESH_Algo* algo = dynamic_cast< const SMESH_Algo* >( *hypIt )) - switch ( algo->GetDim() ) { - case 1: algoShape = TopAbs_EDGE; break; - case 2: algoShape = TopAbs_FACE; break; - case 3: algoShape = TopAbs_SOLID; break; - case 0: algoShape = TopAbs_VERTEX; break; - } - if ( algoShape != TopAbs_SHAPE ) - { - // return all sub-meshes on this dimension - SMESH_subMeshIteratorPtr smIt = theSubMesh->getDependsOnIterator(/*includeSelf=*/false); - while ( smIt->more() ) - { - sm = smIt->next(); - if ( sm->GetSubShape().ShapeType() == algoShape && sm->GetSubMeshDS() ) - theSubMeshList.push_back( sm->GetSubMeshDS() ); - } - return size < theSubMeshList.size(); - } + if ( elementsFound || algoFound ) + break; + if ( sm->GetSubShape().ShapeType() == TopAbs_VERTEX && + mainType != TopAbs_VERTEX ) + break; } + shapeType = sm->GetSubShape().ShapeType(); + if ( !sm->IsEmpty() ) + { + elementsFound = true; + theSubMeshList.push_back( sm->GetSubMeshDS() ); + } + if ( sm->GetAlgo() ) + algoFound = true; } - switch ( aShapeType ) - { - case TopAbs_SOLID: - { - // add sub-mesh of solid itself - if (( aSubMeshDS = aMeshDS->MeshElements( aShape ))) - theSubMeshList.push_back( aSubMeshDS ); - - // and of the first shell - TopExp_Explorer exp( aShape, TopAbs_SHELL ); - if ( exp.More() ) - if (( aSubMeshDS = aMeshDS->MeshElements( exp.Current() ))) - theSubMeshList.push_back( aSubMeshDS ); - break; - } - case TopAbs_WIRE: - case TopAbs_COMPOUND: - case TopAbs_COMPSOLID: - { - // call getSubMeshes() for sub-shapes - list shapeList; - shapeList.push_back( aShape ); - list::iterator sh = shapeList.begin(); - for ( ; sh != shapeList.end(); ++sh ) { - for ( TopoDS_Iterator it( *sh ); it.More(); it.Next() ) { - if (( sm = aMesh->GetSubMeshContaining( it.Value() ))) - getSubMeshes( sm, theSubMeshList ); // add found sub-mesh or explore deeper - else - // no submesh for a compound inside compound - shapeList.push_back( it.Value() ); - } - } - // return only unique sub-meshes - set smSet( theSubMeshList.begin(), theSubMeshList.end() ); - theSubMeshList.assign( smSet.begin(), smSet.end() ); - break; - } - default: - if ( aSubMeshDS ) - theSubMeshList.push_back( aSubMeshDS ); - } return size < theSubMeshList.size(); } @@ -211,15 +148,11 @@ CORBA::Long SMESH_subMesh_i::GetNumberOfElements() return 0; ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId]; - SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS(); - if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() ) - aSubMeshDS = 0; - int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0; + int nbElems = 0; - // volumes are bound to shell TListOfSubMeshes smList; - if ( nbElems == 0 && getSubMeshes( aSubMesh, smList )) + if ( getSubMeshes( aSubMesh, smList )) { TListOfSubMeshes::iterator sm = smList.begin(); for ( ; sm != smList.end(); ++sm ) @@ -249,8 +182,6 @@ CORBA::Long SMESH_subMesh_i::GetNumberOfNodes(CORBA::Boolean all) } ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId]; SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS(); - if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() ) - aSubMeshDS = 0; if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() ) { @@ -298,17 +229,10 @@ SMESH::long_array* SMESH_subMesh_i::GetElementsId() _preMeshInfo->FullLoadFromFile(); ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId]; - SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS(); - if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() ) - aSubMeshDS = 0; - int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0; + int nbElems = 0; TListOfSubMeshes smList; - if ( nbElems ) - smList.push_back( aSubMeshDS ); - - // volumes are bound to shell - if ( nbElems == 0 && getSubMeshes( aSubMesh, smList )) + if ( getSubMeshes( aSubMesh, smList )) { TListOfSubMeshes::iterator sm = smList.begin(); for ( ; sm != smList.end(); ++sm ) @@ -350,17 +274,14 @@ SMESH::long_array* SMESH_subMesh_i::GetElementsByType( SMESH::ElementType theEle _preMeshInfo->FullLoadFromFile(); ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId]; - SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS(); - if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() ) - aSubMeshDS = 0; - // PAL5440, return all nodes belonging to elements of submesh + // PAL5440, return all nodes belonging to elements of the sub-mesh set nodeIds; - int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0; + int nbElems = 0; // volumes may be bound to shell instead of solid TListOfSubMeshes smList; - if ( nbElems == 0 && getSubMeshes( aSubMesh, smList )) + if ( getSubMeshes( aSubMesh, smList )) { TListOfSubMeshes::iterator sm = smList.begin(); for ( ; sm != smList.end(); ++sm ) @@ -386,29 +307,6 @@ SMESH::long_array* SMESH_subMesh_i::GetElementsByType( SMESH::ElementType theEle nbElems += (*sm)->NbElements(); } } - aSubMeshDS = 0; - } - else - { - if ( nbElems ) - smList.push_back( aSubMeshDS ); - } - - if ( theElemType == SMESH::NODE && aSubMeshDS ) - { - SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements(); - if ( eIt->more() ) { - while ( eIt->more() ) { - const SMDS_MeshElement* anElem = eIt->next(); - SMDS_ElemIteratorPtr nIt = anElem->nodesIterator(); - while ( nIt->more() ) - nodeIds.insert( nIt->next()->GetID() ); - } - } else { - SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes(); - while ( nIt->more() ) - nodeIds.insert( nIt->next()->GetID() ); - } } if ( theElemType == SMESH::NODE ) @@ -428,8 +326,7 @@ SMESH::long_array* SMESH_subMesh_i::GetElementsByType( SMESH::ElementType theEle TListOfSubMeshes::iterator sm = smList.begin(); for ( i = 0; sm != smList.end(); sm++ ) { - aSubMeshDS = *sm; - SMDS_ElemIteratorPtr anIt = aSubMeshDS->GetElements(); + SMDS_ElemIteratorPtr anIt = (*sm)->GetElements(); while ( i < n && anIt->more() ) { const SMDS_MeshElement* anElem = anIt->next(); if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType ) diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx index fed12f5a5..c4375bac9 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx @@ -1437,6 +1437,9 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK ) return error("Can't make mesh by source mesh pattern"); + } // end of projection using Pattern mapping + + { // ------------------------------------------------------------------------- // mapper doesn't take care of nodes already existing on edges and vertices, // so we must merge nodes created by it with existing ones @@ -1476,7 +1479,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& continue; // do not treat sm of degen VERTEX } - // Sort new and old nodes of a submesh separately + // Sort new and old nodes of a sub-mesh separately bool isSeam = helper.IsRealSeam( sm->GetId() ); @@ -1600,6 +1603,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& // The mapper can't create quadratic elements, so convert if needed // ---------------------------------------------------------------- + SMDS_ElemIteratorPtr faceIt; faceIt = srcSubMesh->GetSubMeshDS()->GetElements(); bool srcIsQuad = faceIt->next()->IsQuadratic(); faceIt = tgtSubMesh->GetSubMeshDS()->GetElements(); @@ -1613,8 +1617,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces, false); } - - } // end of projection using Pattern mapping + } // end of coincident nodes and quadratic elements treatment if ( !projDone || is1DComputed )