X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MeshEditor.cxx;h=e9c672c1edecea739e5fd7da0021354a878bf369;hp=0673fc64edc86cca16612d6475a9109515e1987f;hb=HEAD;hpb=8fc0f4f35550ae93bf28140d364757453acd42b8 diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 0673fc64e..125bbaa2e 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -62,6 +62,8 @@ #include #include #include +#include +#include #include #include #include @@ -100,6 +102,9 @@ #include "SMESH_TryCatch.hxx" // include after OCCT headers! +#include +#include + #define cast2Node(elem) static_cast( elem ) using namespace std; @@ -161,8 +166,7 @@ SMESH_MeshEditor::ElemFeatures::Init( const SMDS_MeshElement* elem, bool basicOn myIsQuad = elem->IsQuadratic(); if ( myType == SMDSAbs_Volume && !basicOnly ) { - vector quant = static_cast( elem )->GetQuantities(); - myPolyhedQuantities.swap( quant ); + myPolyhedQuantities = static_cast( elem )->GetQuantities(); } } } @@ -187,7 +191,7 @@ SMESH_MeshEditor::AddElement(const vector & node, SMDS_MeshElement* e = 0; int nbnode = node.size(); SMESHDS_Mesh* mesh = GetMeshDS(); - const int ID = features.myID; + const smIdType ID = features.myID; switch ( features.myType ) { case SMDSAbs_Face: @@ -297,6 +301,18 @@ SMESH_MeshEditor::AddElement(const vector & node, node[8], node[9], node[10],node[11], node[12],node[13],node[14] ); } + else if (nbnode == 18) { + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14], + node[15],node[16],node[17],ID ); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14], + node[15],node[16],node[17] ); + } else if (nbnode == 20) { if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], node[4], node[5], node[6], node[7], @@ -378,12 +394,12 @@ SMESH_MeshEditor::AddElement(const vector & node, */ //======================================================================= -SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector & nodeIDs, - const ElemFeatures& features) +SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector & nodeIDs, + const ElemFeatures& features) { vector nodes; nodes.reserve( nodeIDs.size() ); - vector::const_iterator id = nodeIDs.begin(); + vector::const_iterator id = nodeIDs.begin(); while ( id != nodeIDs.end() ) { if ( const SMDS_MeshNode* node = GetMeshDS()->FindNode( *id++ )) nodes.push_back( node ); @@ -399,16 +415,16 @@ SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector & nodeIDs, // Modify a compute state of sub-meshes which become empty //======================================================================= -int SMESH_MeshEditor::Remove (const list< int >& theIDs, - const bool isNodes ) +smIdType SMESH_MeshEditor::Remove (const std::list< smIdType >& theIDs, + const bool isNodes ) { ClearLastCreated(); SMESHDS_Mesh* aMesh = GetMeshDS(); set< SMESH_subMesh *> smmap; - int removed = 0; - list::const_iterator it = theIDs.begin(); + smIdType removed = 0; + list::const_iterator it = theIDs.begin(); for ( ; it != theIDs.end(); it++ ) { const SMDS_MeshElement * elem; if ( isNodes ) @@ -461,10 +477,87 @@ int SMESH_MeshEditor::Remove (const list< int >& theIDs, return removed; } +//================================================================================ +/*! + * \brief Remove a node and fill a hole appeared, by changing surrounding faces + */ +//================================================================================ + +void SMESH_MeshEditor::RemoveNodeWithReconnection( const SMDS_MeshNode* node ) +{ + if ( ! node ) + return; + + if ( node->NbInverseElements( SMDSAbs_Volume ) > 0 ) + throw SALOME_Exception( "RemoveNodeWithReconnection() applies to 2D mesh only" ); + + // check that only triangles surround the node + for ( SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator( SMDSAbs_Face ); fIt->more(); ) + { + const SMDS_MeshElement* face = fIt->next(); + if ( face->GetGeomType() != SMDSGeom_TRIANGLE ) + throw SALOME_Exception( "RemoveNodeWithReconnection() applies to triangle mesh only" ); + if ( face->IsQuadratic() ) + throw SALOME_Exception( "RemoveNodeWithReconnection() applies to linear mesh only" ); + } + + std::vector< const SMDS_MeshNode*> neighbours(2); + SMESH_MeshAlgos::IsOn2DBoundary( node, & neighbours ); + + bool toRemove = ( neighbours.size() > 2 ); // non-manifold ==> just remove + + // if ( neighbours.size() == 2 ) // on boundary + // { + // // check if theNode and neighbours are on a line + // gp_Pnt pN = SMESH_NodeXYZ( node ); + // gp_Pnt p0 = SMESH_NodeXYZ( neighbours[0] ); + // gp_Pnt p1 = SMESH_NodeXYZ( neighbours[1] ); + // double dist01 = p0.Distance( p1 ); + // double tol = 0.01 * dist01; + // double distN = ( gp_Vec( p0, p1 ) ^ gp_Vec( p0, pN )).Magnitude() / dist01; + // bool onLine = distN < tol; + // toRemove = !onLine; + // } + + if ( neighbours.empty() ) // not on boundary + { + TIDSortedElemSet linkedNodes; + GetLinkedNodes( node, linkedNodes, SMDSAbs_Face ); + for ( const SMDS_MeshElement* e : linkedNodes ) neighbours.push_back( cast2Node( e )); + if ( neighbours.empty() ) + toRemove = true; + } + + if ( toRemove ) + { + this->Remove( std::list< smIdType >( 1, node->GetID() ), /*isNode=*/true ); + return; + } + + // choose a node to replace by + const SMDS_MeshNode* nToReplace = nullptr; + SMESH_NodeXYZ nodeXYZ = node; + double minDist = Precision::Infinite(); + for ( const SMDS_MeshNode* n : neighbours ) + { + double dist = nodeXYZ.SquareDistance( n ); + if ( dist < minDist ) + { + minDist = dist; + nToReplace = n; + } + } + + // remove node + replace by nToReplace + std::list< const SMDS_MeshNode* > nodeGroup = { nToReplace, node }; + TListOfListOfNodes nodesToMerge( 1, nodeGroup ); + this->MergeNodes( nodesToMerge ); +} + //================================================================================ /*! * \brief Create 0D elements on all nodes of the given object. - * \param elements - Elements on whose nodes to create 0D elements; if empty, + * \param elements - Elements on whose nodes to create 0D elements; if empty, * the all mesh is treated * \param all0DElems - returns all 0D elements found or created on nodes of \a elements * \param duplicateElements - to add one more 0D element to a node or not @@ -934,24 +1027,24 @@ bool getQuadrangleNodes(const SMDS_MeshNode * theQuadNodes [], { if( tr1->NbNodes() != tr2->NbNodes() ) return false; + // find the 4-th node to insert into tr1 const SMDS_MeshNode* n4 = 0; SMDS_ElemIteratorPtr it = tr2->nodesIterator(); - int i=0; - while ( !n4 && i<3 ) { + for ( int i = 0; !n4 && i < 3; ++i ) + { const SMDS_MeshNode * n = cast2Node( it->next() ); - i++; bool isDiag = ( n == theNode1 || n == theNode2 ); if ( !isDiag ) n4 = n; } + // Make an array of nodes to be in a quadrangle int iNode = 0, iFirstDiag = -1; it = tr1->nodesIterator(); - i=0; - while ( i<3 ) { + for ( int i = 0; i < 3; ++i ) + { const SMDS_MeshNode * n = cast2Node( it->next() ); - i++; bool isDiag = ( n == theNode1 || n == theNode2 ); if ( isDiag ) { if ( iFirstDiag < 0 ) @@ -1066,6 +1159,210 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, return true; } +//======================================================================= +//function : SplitEdge +//purpose : Replace each triangle bound by theNode1-theNode2 segment with +// two triangles by connecting a node made on the link with a node opposite to the link. +//======================================================================= + +void SMESH_MeshEditor::SplitEdge (const SMDS_MeshNode * theNode1, + const SMDS_MeshNode * theNode2, + double thePosition) +{ + ClearLastCreated(); + + SMESHDS_Mesh * mesh = GetMeshDS(); + + // Get triangles and segments to divide + + std::vector diagNodes = { theNode1, theNode2 }; + std::vector foundElems; + if ( !mesh->GetElementsByNodes( diagNodes, foundElems ) || foundElems.empty() ) + throw SALOME_Exception( SMESH_Comment("No triangle is bound by the edge ") + << theNode1->GetID() << " - " << theNode2->GetID()); + + SMESH_MesherHelper helper( *GetMesh() ); + + for ( const SMDS_MeshElement * elem : foundElems ) + { + SMDSAbs_ElementType type = elem->GetType(); + switch ( type ) { + case SMDSAbs_Volume: + throw SALOME_Exception( "Can't split an edge of a volume"); + break; + + case SMDSAbs_Face: + if ( elem->GetGeomType() != SMDSGeom_TRIANGLE ) + throw SALOME_Exception( "Can't split an edge of a face of type other than triangle"); + if ( elem->IsQuadratic() ) + { + helper.SetIsQuadratic( true ); + helper.AddTLinks( static_cast< const SMDS_MeshFace*>( elem )); + helper.SetIsBiQuadratic( elem->GetEntityType() == SMDSEntity_BiQuad_Triangle ); + } + break; + + case SMDSAbs_Edge: + if ( elem->IsQuadratic() ) + { + helper.SetIsQuadratic( true ); + helper.AddTLinks( static_cast< const SMDS_MeshEdge*>( elem )); + } + break; + default:; + } + } + + // Make a new node + + const SMDS_MeshNode* nodeOnLink = helper.GetMediumNode( theNode1, theNode2,/*force3d=*/false ); + + gp_Pnt newNodeXYZ = ( SMESH_NodeXYZ( theNode1 ) * ( 1 - thePosition ) + + SMESH_NodeXYZ( theNode2 ) * thePosition ); + + const TopoDS_Shape& S = mesh->IndexToShape( nodeOnLink->GetShapeID() ); + if ( !S.IsNull() && S.ShapeType() == TopAbs_FACE ) // find newNodeXYZ by UV on FACE + { + Handle(ShapeAnalysis_Surface) surface = helper.GetSurface( TopoDS::Face( S )); + double tol = 100 * helper.MaxTolerance( S ); + gp_Pnt2d uv = surface->ValueOfUV( newNodeXYZ, tol ); + if ( surface->Gap() < SMESH_NodeXYZ( theNode1 ).Distance( theNode2 )) + { + newNodeXYZ = surface->Value( uv ); + if ( SMDS_FacePositionPtr nPos = nodeOnLink->GetPosition()) + nPos->SetParameters( uv.X(), uv.Y() ); + } + } + if ( !S.IsNull() && S.ShapeType() == TopAbs_EDGE ) // find newNodeXYZ by param on EDGE + { + mesh->MoveNode( nodeOnLink, newNodeXYZ.X(), newNodeXYZ.Y(), newNodeXYZ.Z() ); + double u = Precision::Infinite(), tol = 100 * helper.MaxTolerance( S ), distXYZ[4]; + helper.ToFixNodeParameters( true ); + if ( helper.CheckNodeU( TopoDS::Edge( S ), nodeOnLink, u, tol, /*force3D=*/false, distXYZ )) + newNodeXYZ.SetCoord( distXYZ[1], distXYZ[2], distXYZ[3] ); + } + mesh->MoveNode( nodeOnLink, newNodeXYZ.X(), newNodeXYZ.Y(), newNodeXYZ.Z() ); + + // Split triangles and segments + + std::vector nodes( 7 ); + for ( const SMDS_MeshElement * elem : foundElems ) + { + nodes.assign( elem->begin_nodes(), elem->end_nodes() ); + nodes.resize( elem->NbCornerNodes() + 1 ); + nodes.back() = nodes[0]; + + smIdType id = elem->GetID(); + int shapeID = elem->GetShapeID(); + + const SMDS_MeshNode* centralNode = nullptr; + if ( elem->GetEntityType() == SMDSEntity_BiQuad_Triangle ) + centralNode = elem->GetNode( 6 ); + + mesh->RemoveFreeElement( elem, /*sm=*/0, /*fromGroups=*/false ); + if ( centralNode ) + mesh->RemoveFreeNode( centralNode, /*sm=*/0, /*fromGroups=*/true ); + + for ( size_t i = 1; i < nodes.size(); ++i ) + { + const SMDS_MeshNode* n1 = nodes[i-1]; + const SMDS_MeshNode* n2 = nodes[i]; + const SMDS_MeshElement* newElem; + if ( nodes.size() == 4 ) // triangle + { + bool isDiag1 = ( n1 == theNode1 || n1 == theNode2 ); + bool isDiag2 = ( n2 == theNode1 || n2 == theNode2 ); + if ( isDiag1 && isDiag2 ) + continue; + + newElem = helper.AddFace( n1, n2, nodeOnLink, id ); + } + else // segment + { + newElem = helper.AddEdge( n1, nodeOnLink, id ); + } + myLastCreatedElems.push_back( newElem ); + AddToSameGroups( newElem, elem, mesh ); + if ( shapeID ) + mesh->SetMeshElementOnShape( newElem, shapeID ); + id = 0; + } + } + return; +} + +//======================================================================= +//function : SplitFace +//purpose : Split a face into triangles each formed by two nodes of the +// face and a new node added at the given coordinates. +//======================================================================= + +void SMESH_MeshEditor::SplitFace (const SMDS_MeshElement * theFace, + double theX, + double theY, + double theZ ) +{ + ClearLastCreated(); + + if ( !theFace ) + throw SALOME_Exception("Null face given"); + if ( theFace->GetType() != SMDSAbs_Face ) + throw SALOME_Exception("Not a face given"); + + SMESHDS_Mesh * mesh = GetMeshDS(); + + SMESH_MesherHelper helper( *GetMesh() ); + if ( theFace->IsQuadratic() ) + { + helper.SetIsQuadratic( true ); + helper.AddTLinks( static_cast< const SMDS_MeshFace*>( theFace )); + } + const TopoDS_Shape& shape = mesh->IndexToShape( theFace->GetShapeID() ); + helper.SetSubShape( shape ); + helper.SetElementsOnShape( true ); + + // Make a new node + + const SMDS_MeshNode* centralNode = nullptr; + if ( theFace->GetEntityType() == SMDSEntity_BiQuad_Triangle ) + centralNode = theFace->GetNode( 6 ); + else if ( theFace->GetEntityType() == SMDSEntity_BiQuad_Quadrangle ) + centralNode = theFace->GetNode( 8 ); + + if ( centralNode ) + { + helper.SetIsBiQuadratic( true ); + mesh->MoveNode( centralNode, theX, theY, theZ ); + } + else + centralNode = helper.AddNode( theX, theY, theZ ); + + + // Split theFace + + std::vector nodes( theFace->NbNodes() + 1 ); + nodes.assign( theFace->begin_nodes(), theFace->end_nodes() ); + nodes.resize( theFace->NbCornerNodes() + 1 ); + nodes.back() = nodes[0]; + + smIdType id = theFace->GetID(); + int shapeID = theFace->GetShapeID(); + + mesh->RemoveFreeElement( theFace, /*sm=*/0, /*fromGroups=*/false ); + + for ( size_t i = 1; i < nodes.size(); ++i ) + { + const SMDS_MeshElement* newElem = helper.AddFace( nodes[i-1], nodes[i], centralNode, id ); + + myLastCreatedElems.push_back( newElem ); + AddToSameGroups( newElem, theFace, mesh ); + if ( shapeID ) + mesh->SetMeshElementOnShape( newElem, shapeID ); + id = 0; + } + return; +} + //======================================================================= //function : Reorient //purpose : Reverse theElement orientation @@ -1148,69 +1445,88 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem) /*! * \brief Reorient faces. * \param theFaces - the faces to reorient. If empty the whole mesh is meant - * \param theDirection - desired direction of normal of \a theFace - * \param theFace - one of \a theFaces that should be oriented according to - * \a theDirection and whose orientation defines orientation of other faces + * \param theDirection - desired direction of normal of \a theRefFaces. + * It can be (0,0,0) in order to keep orientation of \a theRefFaces. + * \param theRefFaces - correctly oriented faces whose orientation defines + * orientation of other faces. * \return number of reoriented faces. */ //================================================================================ -int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet & theFaces, - const gp_Dir& theDirection, - const SMDS_MeshElement * theFace) +int SMESH_MeshEditor::Reorient2D( TIDSortedElemSet & theFaces, + const gp_Vec& theDirection, + TIDSortedElemSet & theRefFaces, + bool theAllowNonManifold ) { int nbReori = 0; - if ( !theFace || theFace->GetType() != SMDSAbs_Face ) return nbReori; if ( theFaces.empty() ) { - SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(/*idInceasingOrder=true*/); + SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(); while ( fIt->more() ) theFaces.insert( theFaces.end(), fIt->next() ); + + if ( theFaces.empty() ) + return nbReori; } - // orient theFace according to theDirection - gp_XYZ normal; - SMESH_MeshAlgos::FaceNormal( theFace, normal, /*normalized=*/false ); - if ( normal * theDirection.XYZ() < 0 ) - nbReori += Reorient( theFace ); + // orient theRefFaces according to theDirection + if ( theDirection.X() != 0 || theDirection.Y() != 0 || theDirection.Z() != 0 ) + for ( const SMDS_MeshElement* refFace : theRefFaces ) + { + gp_XYZ normal; + SMESH_MeshAlgos::FaceNormal( refFace, normal, /*normalized=*/false ); + if ( normal * theDirection.XYZ() < 0 ) + nbReori += Reorient( refFace ); + } - // Orient other faces + // mark reference faces + GetMeshDS()->SetAllCellsNotMarked(); + for ( const SMDS_MeshElement* refFace : theRefFaces ) + refFace->setIsMarked( true ); - set< const SMDS_MeshElement* > startFaces, visitedFaces; - TIDSortedElemSet avoidSet; - set< SMESH_TLink > checkedLinks; - pair< set< SMESH_TLink >::iterator, bool > linkIt_isNew; + // erase reference faces from theFaces + for ( TIDSortedElemSet::iterator fIt = theFaces.begin(); fIt != theFaces.end(); ) + if ( (*fIt)->isMarked() ) + fIt = theFaces.erase( fIt ); + else + ++fIt; + + if ( theRefFaces.empty() ) + { + theRefFaces.insert( *theFaces.begin() ); + theFaces.erase( theFaces.begin() ); + } + + // Orient theFaces - if ( theFaces.size() > 1 )// leave 1 face to prevent finding not selected faces - theFaces.erase( theFace ); - startFaces.insert( theFace ); + // if ( theFaces.size() > 1 )// leave 1 face to prevent finding not selected faces + // theFaces.erase( theFace ); int nodeInd1, nodeInd2; - const SMDS_MeshElement* otherFace; + const SMDS_MeshElement* refFace, *otherFace; vector< const SMDS_MeshElement* > facesNearLink; vector< std::pair< int, int > > nodeIndsOfFace; + TIDSortedElemSet avoidSet, emptySet; + NCollection_Map< SMESH_TLink, SMESH_TLinkHasher > checkedLinks; - set< const SMDS_MeshElement* >::iterator startFace = startFaces.begin(); - while ( !startFaces.empty() ) + while ( !theRefFaces.empty() ) { - startFace = startFaces.begin(); - theFace = *startFace; - startFaces.erase( startFace ); - if ( !visitedFaces.insert( theFace ).second ) - continue; + auto refFaceIt = theRefFaces.begin(); + refFace = *refFaceIt; + theRefFaces.erase( refFaceIt ); avoidSet.clear(); - avoidSet.insert(theFace); + avoidSet.insert( refFace ); - NLink link( theFace->GetNode( 0 ), (SMDS_MeshNode *) 0 ); + NLink link( refFace->GetNode( 0 ), nullptr ); - const int nbNodes = theFace->NbCornerNodes(); - for ( int i = 0; i < nbNodes; ++i ) // loop on links of theFace + const int nbNodes = refFace->NbCornerNodes(); + for ( int i = 0; i < nbNodes; ++i ) // loop on links of refFace { - link.second = theFace->GetNode(( i+1 ) % nbNodes ); - linkIt_isNew = checkedLinks.insert( link ); - if ( !linkIt_isNew.second ) + link.second = refFace->GetNode(( i+1 ) % nbNodes ); + bool isLinkVisited = checkedLinks.Contains( link ); + if ( isLinkVisited ) { // link has already been checked and won't be encountered more // if the group (theFaces) is manifold @@ -1218,28 +1534,41 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet & theFaces, } else { + checkedLinks.Add( link ); + facesNearLink.clear(); nodeIndsOfFace.clear(); + TIDSortedElemSet::iterator objFaceIt = theFaces.end(); + while (( otherFace = SMESH_MeshAlgos::FindFaceInSet( link.first, link.second, - theFaces, avoidSet, + emptySet, avoidSet, &nodeInd1, &nodeInd2 ))) - if ( otherFace != theFace) + { + if (( otherFace->isMarked() ) || // ref face + (( objFaceIt = theFaces.find( otherFace )) != theFaces.end() )) // object face { facesNearLink.push_back( otherFace ); nodeIndsOfFace.push_back( make_pair( nodeInd1, nodeInd2 )); - avoidSet.insert( otherFace ); } + avoidSet.insert( otherFace ); + } if ( facesNearLink.size() > 1 ) { // NON-MANIFOLD mesh shell ! - // select a face most co-directed with theFace, + if ( !theAllowNonManifold ) + { + throw SALOME_Exception("Non-manifold topology of groups"); + } + // select a face most co-directed with refFace, // other faces won't be visited this time gp_XYZ NF, NOF; - SMESH_MeshAlgos::FaceNormal( theFace, NF, /*normalized=*/false ); + SMESH_MeshAlgos::FaceNormal( refFace, NF, /*normalized=*/false ); double proj, maxProj = -1; - for ( size_t i = 0; i < facesNearLink.size(); ++i ) { + for ( size_t i = 0; i < facesNearLink.size(); ++i ) + { SMESH_MeshAlgos::FaceNormal( facesNearLink[i], NOF, /*normalized=*/false ); - if (( proj = Abs( NF * NOF )) > maxProj ) { + if (( proj = Abs( NF * NOF )) > maxProj ) + { maxProj = proj; otherFace = facesNearLink[i]; nodeInd1 = nodeIndsOfFace[i].first; @@ -1247,9 +1576,9 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet & theFaces, } } // not to visit rejected faces - for ( size_t i = 0; i < facesNearLink.size(); ++i ) - if ( facesNearLink[i] != otherFace && theFaces.size() > 1 ) - visitedFaces.insert( facesNearLink[i] ); + // for ( size_t i = 0; i < facesNearLink.size(); ++i ) + // if ( facesNearLink[i] != otherFace && theFaces.size() > 1 ) + // visitedFaces.insert( facesNearLink[i] ); } else if ( facesNearLink.size() == 1 ) { @@ -1257,20 +1586,36 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet & theFaces, nodeInd1 = nodeIndsOfFace.back().first; nodeInd2 = nodeIndsOfFace.back().second; } - if ( otherFace && otherFace != theFace) + if ( otherFace ) { - // link must be reverse in otherFace if orientation to otherFace - // is same as that of theFace - if ( abs(nodeInd2-nodeInd1) == 1 ? nodeInd2 > nodeInd1 : nodeInd1 > nodeInd2 ) + // link must be reverse in otherFace if orientation of otherFace + // is same as that of refFace + if ( abs( nodeInd2 - nodeInd1 ) == 1 ? nodeInd2 > nodeInd1 : nodeInd1 > nodeInd2 ) { + if ( otherFace->isMarked() ) + throw SALOME_Exception("Different orientation of reference faces"); nbReori += Reorient( otherFace ); } - startFaces.insert( otherFace ); + if ( !otherFace->isMarked() ) + { + theRefFaces.insert( otherFace ); + if ( objFaceIt != theFaces.end() ) + theFaces.erase( objFaceIt ); + } } } - std::swap( link.first, link.second ); // reverse the link + link.first = link.second; // reverse the link + + } // loop on links of refFace + + if ( theRefFaces.empty() && !theFaces.empty() ) + { + theRefFaces.insert( *theFaces.begin() ); + theFaces.erase( theFaces.begin() ); } - } + + } // while ( !theRefFaces.empty() ) + return nbReori; } @@ -1493,9 +1838,12 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems) SMESH_MesherHelper helper( *GetMesh() ); helper.SetElementsOnShape( true ); - SMDS_ElemIteratorPtr faceIt; - if ( theElems.empty() ) faceIt = GetMeshDS()->elementsIterator(SMDSAbs_Face); - else faceIt = SMESHUtils::elemSetIterator( theElems ); + // get standalone groups of faces + vector< SMDS_MeshGroup* > allFaceGroups, faceGroups; + for ( SMESHDS_GroupBase* grBase : GetMeshDS()->GetGroups() ) + if ( SMESHDS_Group* group = dynamic_cast( grBase )) + if ( group->GetType() == SMDSAbs_Face && !group->IsEmpty() ) + allFaceGroups.push_back( & group->SMDSGroup() ); bool checkUV; gp_XY uv [9]; uv[8] = gp_XY(0,0); @@ -1506,6 +1854,10 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems) Handle(Geom_Surface) surface; TopLoc_Location loc; + SMDS_ElemIteratorPtr faceIt; + if ( theElems.empty() ) faceIt = GetMeshDS()->elementsIterator(SMDSAbs_Face); + else faceIt = SMESHUtils::elemSetIterator( theElems ); + while ( faceIt->more() ) { const SMDS_MeshElement* quad = faceIt->next(); @@ -1582,13 +1934,19 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems) myLastCreatedNodes.push_back( nCentral ); } - // create 4 triangles - helper.SetIsQuadratic ( nodes.size() > 4 ); helper.SetIsBiQuadratic( nodes.size() == 9 ); if ( helper.GetIsQuadratic() ) helper.AddTLinks( static_cast< const SMDS_MeshFace*>( quad )); + // select groups to update + faceGroups.clear(); + for ( SMDS_MeshGroup* group : allFaceGroups ) + if ( group->Remove( quad )) + faceGroups.push_back( group ); + + // create 4 triangles + GetMeshDS()->RemoveFreeElement( quad, subMeshDS, /*fromGroups=*/false ); for ( int i = 0; i < 4; ++i ) @@ -1596,8 +1954,9 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems) SMDS_MeshElement* tria = helper.AddFace( nodes[ i ], nodes[(i+1)%4], nCentral ); - ReplaceElemInGroups( tria, quad, GetMeshDS() ); myLastCreatedElems.push_back( tria ); + for ( SMDS_MeshGroup* group : faceGroups ) + group->Add( tria ); } } } @@ -1783,6 +2142,17 @@ namespace TSplitMethod( int nbTet=0, const int* conn=0, bool addNode=false) : _nbSplits(nbTet), _nbCorners(4), _connectivity(conn), _baryNode(addNode), _ownConn(false) {} ~TSplitMethod() { if ( _ownConn ) delete [] _connectivity; _connectivity = 0; } + TSplitMethod(const TSplitMethod &splitMethod) + : _nbSplits(splitMethod._nbSplits), + _nbCorners(splitMethod._nbCorners), + _baryNode(splitMethod._baryNode), + _ownConn(splitMethod._ownConn), + _faceBaryNode(splitMethod._faceBaryNode) + { + _connectivity = splitMethod._connectivity; + const_cast(splitMethod)._connectivity = nullptr; + const_cast(splitMethod)._ownConn = false; + } bool hasFacet( const TTriangleFacet& facet ) const { if ( _nbCorners == 4 ) @@ -1902,7 +2272,7 @@ namespace } for ( int variant = 0; variant < nbVariants && method._nbSplits == 0; ++variant ) { - // check method compliancy with adjacent tetras, + // check method compliance with adjacent tetras, // all found splits must be among facets of tetras described by this method method = TSplitMethod( nbTet, connVariants[variant] ); if ( hasAdjacentSplits && method._nbSplits > 0 ) @@ -2033,6 +2403,8 @@ namespace const int methodFlags, const int facetToSplit) { + TSplitMethod method; + // order of facets in HEX according to SMDS_VolumeTool::Hexa_F : // B, T, L, B, R, F const int iF = ( facetToSplit < 2 ) ? 0 : 1 + ( facetToSplit-2 ) % 2; // [0,1,2] @@ -2063,12 +2435,12 @@ namespace to4methods[iF]._nbSplits = 4; to4methods[iF]._nbCorners = 6; } - return to4methods[iF]; + method = to4methods[iF]; + to4methods[iF]._connectivity = method._connectivity; // as copy ctor resets _connectivity + return method; } // else if ( methodFlags == HEXA_TO_2_PRISMS ) - TSplitMethod method; - const int iQ = vol.Element()->IsQuadratic() ? 2 : 1; const int nbVariants = 2, nbSplits = 2; @@ -2101,7 +2473,7 @@ namespace // there are adjacent prism for ( int variant = 0; variant < nbVariants; ++variant ) { - // check method compliancy with adjacent prisms, + // check method compliance with adjacent prisms, // the found prism facets must be among facets of prisms described by current method method._nbSplits = nbSplits; method._nbCorners = 6; @@ -2180,7 +2552,7 @@ namespace */ //======================================================================= - struct TVolumeFaceKey: pair< pair< int, int>, pair< int, int> > + struct TVolumeFaceKey: pair< pair< smIdType, smIdType>, pair< smIdType, smIdType> > { TVolumeFaceKey( SMDS_VolumeTool& vol, int iF ) { @@ -3094,10 +3466,10 @@ public: :myMesh( theMesh ), myMaxID( theMesh->MaxNodeID() + 1) {} - long GetLinkID (const SMDS_MeshNode * n1, + smIdType GetLinkID (const SMDS_MeshNode * n1, const SMDS_MeshNode * n2) const { - return ( Min(n1->GetID(),n2->GetID()) * myMaxID + Max(n1->GetID(),n2->GetID())); + return ( std::min(n1->GetID(),n2->GetID()) * myMaxID + std::max(n1->GetID(),n2->GetID())); } bool GetNodes (const long theLinkID, @@ -3480,6 +3852,68 @@ void SMESH_MeshEditor::GetLinkedNodes( const SMDS_MeshNode* theNode, } } +//======================================================================= +//function : averageBySurface +//purpose : Auxiliar function to treat properly nodes in periodic faces in the laplacian smoother +//======================================================================= +void averageBySurface( const Handle(Geom_Surface)& theSurface, const SMDS_MeshNode* refNode, + TIDSortedElemSet& nodeSet, map< const SMDS_MeshNode*, gp_XY* >& theUVMap, double * coord ) +{ + if ( theSurface.IsNull() ) + { + TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin(); + for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ ) + { + const SMDS_MeshNode* node = cast2Node(*nodeSetIt); + coord[0] += node->X(); + coord[1] += node->Y(); + coord[2] += node->Z(); + } + } + else + { + Standard_Real Umin,Umax,Vmin,Vmax; + theSurface->Bounds( Umin, Umax, Vmin, Vmax ); + ASSERT( theUVMap.find( refNode ) != theUVMap.end() ); + gp_XY* nodeUV = theUVMap[ refNode ]; + Standard_Real uref = nodeUV->X(); + Standard_Real vref = nodeUV->Y(); + + TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin(); + for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ ) + { + const SMDS_MeshNode* node = cast2Node(*nodeSetIt); + ASSERT( theUVMap.find( node ) != theUVMap.end() ); + gp_XY* uv = theUVMap[ node ]; + + if ( theSurface->IsUPeriodic() || theSurface->IsVPeriodic() ) + { + Standard_Real u = uv->X(); + Standard_Real v = uv->Y(); + Standard_Real uCorrected = u; + Standard_Real vCorrected = v; + bool isUTobeCorrected = (std::fabs( uref - u ) >= 0.7 * std::fabs( Umax - Umin )); + bool isVTobeCorrected = (std::fabs( vref - v ) >= 0.7 * std::fabs( Vmax - Vmin )); + + if( isUTobeCorrected ) + uCorrected = uref > u ? Umax + std::fabs(Umin - u) : Umin - std::fabs(Umax - u); + + if( isVTobeCorrected ) + vCorrected = vref > v ? Vmax + std::fabs(Vmin - v) : Vmin - std::fabs(Vmax - v); + + coord[0] += uCorrected; + coord[1] += vCorrected; + + } + else + { + coord[0] += uv->X(); + coord[1] += uv->Y(); + } + } + } +} + //======================================================================= //function : laplacianSmooth //purpose : pulls theNode toward the center of surrounding nodes directly @@ -3496,26 +3930,14 @@ void laplacianSmooth(const SMDS_MeshNode* theNode, SMESH_MeshEditor::GetLinkedNodes( theNode, nodeSet, SMDSAbs_Face ); // compute new coodrs + double coord[] = { 0., 0., 0. }; + + averageBySurface( theSurface, theNode, nodeSet, theUVMap, coord ); - double coord[] = { 0., 0., 0. }; - TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin(); - for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ ) { - const SMDS_MeshNode* node = cast2Node(*nodeSetIt); - if ( theSurface.IsNull() ) { // smooth in 3D - coord[0] += node->X(); - coord[1] += node->Y(); - coord[2] += node->Z(); - } - else { // smooth in 2D - ASSERT( theUVMap.find( node ) != theUVMap.end() ); - gp_XY* uv = theUVMap[ node ]; - coord[0] += uv->X(); - coord[1] += uv->Y(); - } - } int nbNodes = nodeSet.size(); if ( !nbNodes ) return; + coord[0] /= nbNodes; coord[1] /= nbNodes; @@ -3525,7 +3947,7 @@ void laplacianSmooth(const SMDS_MeshNode* theNode, gp_Pnt p3d = theSurface->Value( coord[0], coord[1] ); coord[0] = p3d.X(); coord[1] = p3d.Y(); - coord[2] = p3d.Z(); + coord[2] = p3d.Z(); } else coord[2] /= nbNodes; @@ -3535,6 +3957,72 @@ void laplacianSmooth(const SMDS_MeshNode* theNode, const_cast< SMDS_MeshNode* >( theNode )->setXYZ(coord[0],coord[1],coord[2]); } +//======================================================================= +//function : correctTheValue +//purpose : Given a boundaries of parametric space determine if the node coordinate (u,v) need correction +// based on the reference coordinate (uref,vref) +//======================================================================= +void correctTheValue( Standard_Real Umax, Standard_Real Umin, Standard_Real Vmax, Standard_Real Vmin, + Standard_Real uref, Standard_Real vref, Standard_Real &u, Standard_Real &v ) +{ + bool isUTobeCorrected = (std::fabs( uref - u ) >= 0.7 * std::fabs( Umax - Umin )); + bool isVTobeCorrected = (std::fabs( vref - v ) >= 0.7 * std::fabs( Vmax - Vmin )); + if ( isUTobeCorrected ) + u = std::fabs(u-Umin) < 1e-7 ? Umax : Umin; + if ( isVTobeCorrected ) + v = std::fabs(v-Vmin) < 1e-7 ? Vmax : Vmin; +} + +//======================================================================= +//function : averageByElement +//purpose : Auxiliar function to treat properly nodes in periodic faces in the centroidal smoother +//======================================================================= +void averageByElement( const Handle(Geom_Surface)& theSurface, const SMDS_MeshNode* refNode, const SMDS_MeshElement* elem, + map< const SMDS_MeshNode*, gp_XY* >& theUVMap, SMESH::Controls::TSequenceOfXYZ& aNodePoints, + gp_XYZ& elemCenter ) +{ + int nn = elem->NbNodes(); + if(elem->IsQuadratic()) nn = nn/2; + int i=0; + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + Standard_Real Umin,Umax,Vmin,Vmax; + while ( i( itN->next() ); + i++; + gp_XYZ aP( aNode->X(), aNode->Y(), aNode->Z() ); + aNodePoints.push_back( aP ); + if ( !theSurface.IsNull() ) // smooth in 2D + { + ASSERT( theUVMap.find( aNode ) != theUVMap.end() ); + gp_XY* uv = theUVMap[ aNode ]; + + if ( theSurface->IsUPeriodic() || theSurface->IsVPeriodic() ) + { + theSurface->Bounds( Umin, Umax, Vmin, Vmax ); + Standard_Real u = uv->X(); + Standard_Real v = uv->Y(); + bool isSingularPoint = std::fabs(u - Umin) < 1e-7 || std::fabs(v - Vmin) < 1e-7 || std::fabs(u - Umax) < 1e-7 || std::fabs( v - Vmax ) < 1e-7; + if ( !isSingularPoint ) + { + aP.SetCoord( uv->X(), uv->Y(), 0. ); + } + else + { + gp_XY* refPoint = theUVMap[ refNode ]; + Standard_Real uref = refPoint->X(); + Standard_Real vref = refPoint->Y(); + correctTheValue( Umax, Umin, Vmax, Vmin, uref, vref, u, v ); + aP.SetCoord( u, v, 0. ); + } + } + else + aP.SetCoord( uv->X(), uv->Y(), 0. ); + } + elemCenter += aP; + } +} + //======================================================================= //function : centroidalSmooth //purpose : pulls theNode toward the element-area-weighted centroid of the @@ -3549,48 +4037,46 @@ void centroidalSmooth(const SMDS_MeshNode* theNode, SMESH::Controls::Area anAreaFunc; double totalArea = 0.; int nbElems = 0; - // compute new XYZ - + bool notToMoveNode = false; + // Do not correct singular nodes + if ( !theSurface.IsNull() && (theSurface->IsUPeriodic() || theSurface->IsVPeriodic()) ) + { + Standard_Real Umin,Umax,Vmin,Vmax; + theSurface->Bounds( Umin, Umax, Vmin, Vmax ); + gp_XY* uv = theUVMap[ theNode ]; + Standard_Real u = uv->X(); + Standard_Real v = uv->Y(); + notToMoveNode = std::fabs(u - Umin) < 1e-7 || std::fabs(v - Vmin) < 1e-7 || std::fabs(u - Umax) < 1e-7 || std::fabs( v - Vmax ) < 1e-7; + } + SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(SMDSAbs_Face); - while ( elemIt->more() ) + while ( elemIt->more() && !notToMoveNode ) { const SMDS_MeshElement* elem = elemIt->next(); nbElems++; gp_XYZ elemCenter(0.,0.,0.); SMESH::Controls::TSequenceOfXYZ aNodePoints; - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); int nn = elem->NbNodes(); if(elem->IsQuadratic()) nn = nn/2; - int i=0; - //while ( itN->more() ) { - while ( i( itN->next() ); - i++; - gp_XYZ aP( aNode->X(), aNode->Y(), aNode->Z() ); - aNodePoints.push_back( aP ); - if ( !theSurface.IsNull() ) { // smooth in 2D - ASSERT( theUVMap.find( aNode ) != theUVMap.end() ); - gp_XY* uv = theUVMap[ aNode ]; - aP.SetCoord( uv->X(), uv->Y(), 0. ); - } - elemCenter += aP; - } + averageByElement( theSurface, theNode, elem, theUVMap, aNodePoints, elemCenter ); + double elemArea = anAreaFunc.GetValue( aNodePoints ); totalArea += elemArea; elemCenter /= nn; aNewXYZ += elemCenter * elemArea; } aNewXYZ /= totalArea; - if ( !theSurface.IsNull() ) { + + if ( !theSurface.IsNull() && !notToMoveNode ) { theUVMap[ theNode ]->SetCoord( aNewXYZ.X(), aNewXYZ.Y() ); aNewXYZ = theSurface->Value( aNewXYZ.X(), aNewXYZ.Y() ).XYZ(); } // move node - - const_cast< SMDS_MeshNode* >( theNode )->setXYZ(aNewXYZ.X(),aNewXYZ.Y(),aNewXYZ.Z()); + if ( !notToMoveNode ) + const_cast< SMDS_MeshNode* >( theNode )->setXYZ(aNewXYZ.X(),aNewXYZ.Y(),aNewXYZ.Z()); } //======================================================================= @@ -3604,7 +4090,7 @@ static bool getClosestUV (Extrema_GenExtPS& projector, { projector.Perform( point ); if ( projector.IsDone() ) { - double u, v, minVal = DBL_MAX; + double u = 0, v = 0, minVal = DBL_MAX; for ( int i = projector.NbExt(); i > 0; i-- ) if ( projector.SquareDistance( i ) < minVal ) { minVal = projector.SquareDistance( i ); @@ -3893,7 +4379,8 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, if ( !BRep_Tool::IsClosed( edge, face )) continue; SMESHDS_SubMesh* sm = aMesh->MeshElements( edge ); - if ( !sm ) continue; + if ( !sm ) + continue; // find out which parameter varies for a node on seam double f,l; gp_Pnt2d uv1, uv2; @@ -4267,7 +4754,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, std::swap( itNN[0], itNN[1] ); std::swap( prevNod[0], prevNod[1] ); std::swap( nextNod[0], nextNod[1] ); - std::swap( isSingleNode[0], isSingleNode[1] ); + std::vector::swap(isSingleNode[0], isSingleNode[1]); if ( nbSame > 0 ) sames[0] = 1 - sames[0]; iNotSameNode = 1 - iNotSameNode; @@ -4850,13 +5337,12 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1],commonNodes[2])); else srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1])); -#ifdef _DEBUG_ - if ( !srcEdges.back() ) + + if (SALOME::VerbosityActivated() && !srcEdges.back()) { cout << "SMESH_MeshEditor::makeWalls(), no source edge found for a free face #" - << iF << " of volume #" << vTool.ID() << endl; + << iF << " of volume #" << vTool.ID() << endl; } -#endif } } if ( freeInd.empty() ) @@ -5641,10 +6127,10 @@ makeNodesByNormal2D( SMESHDS_Mesh* mesh, //======================================================================= int SMESH_MeshEditor::ExtrusParam:: -makeNodesByNormal1D( SMESHDS_Mesh* mesh, - const SMDS_MeshNode* srcNode, - std::list & newNodes, - const bool makeMediumNodes) +makeNodesByNormal1D( SMESHDS_Mesh* /*mesh*/, + const SMDS_MeshNode* /*srcNode*/, + std::list & /*newNodes*/, + const bool /*makeMediumNodes*/) { throw SALOME_Exception("Extrusion 1D by Normal not implemented"); return 0; @@ -6045,6 +6531,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], if ( nbEdges > 0 ) break; } + // fall through default: { for ( int di = -1; di <= 1; di += 2 ) @@ -6442,13 +6929,12 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem // copy offsetMesh to theTgtMesh - int idShift = meshDS->MaxNodeID(); + smIdType idShift = meshDS->MaxNodeID(); for ( size_t i = 0; i < new2OldNodes.size(); ++i ) if ( const SMDS_MeshNode* n = new2OldNodes[ i ].first ) { -#ifndef _DEBUG_ - if ( n->NbInverseElements() > 0 ) -#endif + + if (!SALOME::VerbosityActivated() || n->NbInverseElements() > 0 ) { const SMDS_MeshNode* n2 = tgtMeshDS->AddNodeWithID( n->X(), n->Y(), n->Z(), idShift + n->GetID() ); @@ -6812,7 +7298,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes, TNodeNodeMap nodeNodeMap; // node to replace - new node set elems; // all elements with changed nodes - list< int > rmElemIds, rmNodeIds; + list< smIdType > rmElemIds, rmNodeIds; vector< ElemFeatures > newElemDefs; // Fill nodeNodeMap and elems @@ -6911,6 +7397,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes, { const SMDS_MeshElement* elem = *eIt; SMESHDS_SubMesh* sm = mesh->MeshElements( elem->getshapeId() ); + bool marked = elem->isMarked(); bool keepElem = applyMerge( elem, newElemDefs, nodeNodeMap, /*noHoles=*/false ); if ( !keepElem ) @@ -6918,9 +7405,19 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes, for ( size_t i = 0; i < newElemDefs.size(); ++i ) { - if ( i > 0 || !mesh->ChangeElementNodes( elem, - & newElemDefs[i].myNodes[0], - newElemDefs[i].myNodes.size() )) + bool elemChanged = false; + if ( i == 0 ) + { + if ( elem->GetGeomType() == SMDSGeom_POLYHEDRA ) + elemChanged = mesh->ChangePolyhedronNodes( elem, + newElemDefs[i].myNodes, + newElemDefs[i].myPolyhedQuantities ); + else + elemChanged = mesh->ChangeElementNodes( elem, + & newElemDefs[i].myNodes[0], + newElemDefs[i].myNodes.size() ); + } + if ( i > 0 || !elemChanged ) { if ( i == 0 ) { @@ -6937,6 +7434,8 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes, sm->AddElement( newElem ); if ( elem != newElem ) ReplaceElemInGroups( elem, newElem, mesh ); + if ( marked && newElem ) + newElem->setIsMarked( true ); } } } @@ -7087,6 +7586,7 @@ bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem, // each face has to be analyzed in order to check volume validity if ( const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( elem )) { + toRemove = false; int nbFaces = aPolyedre->NbFaces(); vector& poly_nodes = newElemDefs[0].myNodes; @@ -7407,14 +7907,18 @@ bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem, // purpose : allow comparing elements basing on their nodes // ======================================================== -class ComparableElement : public boost::container::flat_set< int > +struct ComparableElementHasher; + +class ComparableElement : public boost::container::flat_set< smIdType > { - typedef boost::container::flat_set< int > int_set; + typedef boost::container::flat_set< smIdType > int_set; const SMDS_MeshElement* myElem; - int mySumID; + smIdType mySumID; mutable int myGroupID; + friend ComparableElementHasher; + public: ComparableElement( const SMDS_MeshElement* theElem ): @@ -7423,7 +7927,7 @@ public: this->reserve( theElem->NbNodes() ); for ( SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator(); nodeIt->more(); ) { - int id = nodeIt->next()->GetID(); + smIdType id = nodeIt->next()->GetID(); mySumID += id; this->insert( id ); } @@ -7435,23 +7939,38 @@ public: //int& GroupID() const { return const_cast< int& >( myGroupID ); } ComparableElement( const ComparableElement& theSource ) // move copy + : int_set() { ComparableElement& src = const_cast< ComparableElement& >( theSource ); - (int_set&) (*this ) = boost::move( src ); + (int_set&) (*this ) = std::move( src ); myElem = src.myElem; mySumID = src.mySumID; myGroupID = src.myGroupID; } +}; +struct ComparableElementHasher +{ +#if OCC_VERSION_LARGE < 0x07080000 static int HashCode(const ComparableElement& se, int limit ) { - return ::HashCode( se.mySumID, limit ); + return ::HashCode( FromSmIdType(se.mySumID), limit ); } static Standard_Boolean IsEqual(const ComparableElement& se1, const ComparableElement& se2 ) { return ( se1 == se2 ); } +#else + size_t operator()(const ComparableElement& se) const + { + return static_cast(FromSmIdType(se.mySumID)); + } + bool operator()(const ComparableElement& se1, const ComparableElement& se2) const + { + return ( se1 == se2 ); + } +#endif }; //======================================================================= @@ -7469,8 +7988,8 @@ void SMESH_MeshEditor::FindEqualElements( TIDSortedElemSet & theElements, if ( theElements.empty() ) elemIt = GetMeshDS()->elementsIterator(); else elemIt = SMESHUtils::elemSetIterator( theElements ); - typedef NCollection_Map< ComparableElement, ComparableElement > TMapOfElements; - typedef std::list TGroupOfElems; + typedef NCollection_Map< ComparableElement, ComparableElementHasher > TMapOfElements; + typedef std::list TGroupOfElems; TMapOfElements mapOfElements; std::vector< TGroupOfElems > arrayOfGroups; TGroupOfElems groupOfElems; @@ -7516,7 +8035,7 @@ void SMESH_MeshEditor::MergeElements(TListOfListOfElementsID & theGroupsOfElemen { ClearLastCreated(); - typedef list TListOfIDs; + typedef list TListOfIDs; TListOfIDs rmElemIds; // IDs of elems to remove SMESHDS_Mesh* aMesh = GetMeshDS(); @@ -8231,8 +8750,8 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, TListOfListOfElementsID::iterator itGroups = equalGroups.begin(); for ( ; itGroups != equalGroups.end(); ++itGroups ) { - list< int >& group = *itGroups; - list< int >::iterator id = group.begin(); + list< smIdType >& group = *itGroups; + list< smIdType >::iterator id = group.begin(); for ( ++id; id != group.end(); ++id ) if ( const SMDS_MeshElement* seg = GetMeshDS()->FindElement( *id )) segments.erase( seg ); @@ -8664,12 +9183,12 @@ namespace */ //======================================================================= -int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh * theSm, - SMESH_MesherHelper& theHelper, - const bool theForce3d) +smIdType SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh * theSm, + SMESH_MesherHelper& theHelper, + const bool theForce3d) { //MESSAGE("convertElemToQuadratic"); - int nbElem = 0; + smIdType nbElem = 0; if( !theSm ) return nbElem; vector nbNodeInFaces; @@ -8722,7 +9241,7 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh * theSm, } // get elem data needed to re-create it // - const int id = elem->GetID(); + const smIdType id = elem->GetID(); const int nbNodes = elem->NbCornerNodes(); nodes.assign(elem->begin_nodes(), elem->end_nodes()); if ( aGeomType == SMDSEntity_Polyhedra ) @@ -8817,7 +9336,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT aHelper.ToFixNodeParameters( true ); // convert elements assigned to sub-meshes - int nbCheckedElems = 0; + smIdType nbCheckedElems = 0; if ( myMesh->HasShapeToMesh() ) { if ( SMESH_subMesh *aSubMesh = myMesh->GetSubMeshContaining(myMesh->GetShapeToMesh())) @@ -8834,7 +9353,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT } // convert elements NOT assigned to sub-meshes - int totalNbElems = meshDS->NbEdges() + meshDS->NbFaces() + meshDS->NbVolumes(); + smIdType totalNbElems = meshDS->NbEdges() + meshDS->NbFaces() + meshDS->NbVolumes(); if ( nbCheckedElems < totalNbElems ) // not all elements are in sub-meshes { aHelper.SetElementsOnShape(false); @@ -8847,7 +9366,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT const SMDS_MeshEdge* edge = aEdgeItr->next(); if ( !edge->IsQuadratic() ) { - int id = edge->GetID(); + smIdType id = edge->GetID(); const SMDS_MeshNode* n1 = edge->GetNode(0); const SMDS_MeshNode* n2 = edge->GetNode(1); @@ -8888,7 +9407,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT if ( alreadyOK ) continue; - const int id = face->GetID(); + const smIdType id = face->GetID(); vector nodes ( face->begin_nodes(), face->end_nodes()); meshDS->RemoveFreeElement(face, smDS, /*fromGroups=*/false); @@ -8944,7 +9463,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT continue; } } - const int id = volume->GetID(); + const smIdType id = volume->GetID(); vector nodes (volume->begin_nodes(), volume->end_nodes()); if ( type == SMDSEntity_Polyhedra ) nbNodeInFaces = static_cast(volume)->GetQuantities(); @@ -9124,7 +9643,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, if ( alreadyOK ) continue; const SMDSAbs_ElementType type = elem->GetType(); - const int id = elem->GetID(); + const smIdType id = elem->GetID(); const int nbNodes = elem->NbCornerNodes(); vector nodes ( elem->begin_nodes(), elem->end_nodes()); @@ -9185,15 +9704,15 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, //======================================================================= /*! * \brief Convert quadratic elements to linear ones and remove quadratic nodes - * \return int - nb of checked elements + * \return smIdType - nb of checked elements */ //======================================================================= -int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm, - SMDS_ElemIteratorPtr theItr, - const int theShapeID) +smIdType SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm, + SMDS_ElemIteratorPtr theItr, + const int /*theShapeID*/) { - int nbElem = 0; + smIdType nbElem = 0; SMESHDS_Mesh* meshDS = GetMeshDS(); ElemFeatures elemType; vector nodes; @@ -9238,7 +9757,7 @@ int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm, bool SMESH_MeshEditor::ConvertFromQuadratic() { - int nbCheckedElems = 0; + smIdType nbCheckedElems = 0; if ( myMesh->HasShapeToMesh() ) { if ( SMESH_subMesh *aSubMesh = myMesh->GetSubMeshContaining(myMesh->GetShapeToMesh())) @@ -9252,7 +9771,7 @@ bool SMESH_MeshEditor::ConvertFromQuadratic() } } - int totalNbElems = + smIdType totalNbElems = GetMeshDS()->NbEdges() + GetMeshDS()->NbFaces() + GetMeshDS()->NbVolumes(); if ( nbCheckedElems < totalNbElems ) // not all elements are in submeshes { @@ -9291,7 +9810,7 @@ void SMESH_MeshEditor::ConvertFromQuadratic(TIDSortedElemSet& theElements) if ( theElements.empty() ) return; // collect IDs of medium nodes of theElements; some of these nodes will be removed - set mediumNodeIDs; + set mediumNodeIDs; TIDSortedElemSet::iterator eIt = theElements.begin(); for ( ; eIt != theElements.end(); ++eIt ) { @@ -9310,7 +9829,7 @@ void SMESH_MeshEditor::ConvertFromQuadratic(TIDSortedElemSet& theElements) // get remaining medium nodes TIDSortedNodeSet mediumNodes; - set::iterator nIdsIt = mediumNodeIDs.begin(); + set::iterator nIdsIt = mediumNodeIDs.begin(); for ( ; nIdsIt != mediumNodeIDs.end(); ++nIdsIt ) if ( const SMDS_MeshNode* n = GetMeshDS()->FindNode( *nIdsIt )) mediumNodes.insert( mediumNodes.end(), n ); @@ -9338,7 +9857,7 @@ void SMESH_MeshEditor::ConvertFromQuadratic(TIDSortedElemSet& theElements) const SMDS_MeshElement* eComplex = invIt2->next(); if ( eComplex->IsQuadratic() && !allMediumNodesIn( eComplex, mediumNodes)) { - int nbCommonNodes = SMESH_MeshAlgos::GetCommonNodes( e, eComplex ).size(); + int nbCommonNodes = SMESH_MeshAlgos::NbCommonNodes( e, eComplex ); if ( nbCommonNodes == e->NbNodes()) { complexFound = true; @@ -9799,7 +10318,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, if ( aResult != SEW_OK) return aResult; - list< int > nodeIDsToRemove; + list< smIdType > nodeIDsToRemove; vector< const SMDS_MeshNode*> nodes; ElemFeatures elemType; @@ -9880,10 +10399,10 @@ SMESH_MeshEditor::FindMatchingNodes(set& theSide1, set * faceSetPtr[] = { &theSide1, &theSide2 }; nReplaceMap.clear(); - if ( theFirstNode1 != theFirstNode2 ) - nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 )); - if ( theSecondNode1 != theSecondNode2 ) - nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 )); + //if ( theFirstNode1 != theFirstNode2 ) + nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 )); + //if ( theSecondNode1 != theSecondNode2 ) + nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 )); set< SMESH_TLink > linkSet; // set of nodes where order of nodes is ignored linkSet.insert( SMESH_TLink( theFirstNode1, theSecondNode1 )); @@ -10173,7 +10692,7 @@ namespace // automatically find theAffectedElems for DoubleNodes() if ( SMESH_MeshAlgos::FaceNormal( _elems[1], norm )) avgNorm += norm; - gp_XYZ bordDir( SMESH_NodeXYZ( _nodes[0] ) - SMESH_NodeXYZ( _nodes[1] )); + gp_XYZ bordDir( SMESH_NodeXYZ( this->_nodes[0] ) - SMESH_NodeXYZ( this->_nodes[1] )); norm = bordDir ^ avgNorm; } else @@ -10199,7 +10718,8 @@ namespace // automatically find theAffectedElems for DoubleNodes() if ( maxX < 0 ) { _elems[0]->setIsMarked( false ); - _elems[1]->setIsMarked( true ); + if ( _elems[1] ) + _elems[1]->setIsMarked( true ); } } @@ -10371,7 +10891,11 @@ namespace // automatically find theAffectedElems for DoubleNodes() { fissure.reserve( theElemsOrNodes.size() ); for ( ; elIt != theElemsOrNodes.end(); ++elIt ) + { fissure.push_back( std::move( FissureBorder( *elIt, elemsByFacet ))); + if ( !fissure.back()._elems[1] ) + fissure.pop_back(); + } } if ( fissure.empty() ) return; @@ -10734,7 +11258,23 @@ bool SMESH_MeshEditor::doubleNodes(SMESHDS_Mesh* theMeshDS, if ( theIsDoubleElem ) AddElement( newNodes, elemType.Init( anElem, /*basicOnly=*/false )); else - theMeshDS->ChangeElementNodes( anElem, &newNodes[ 0 ], newNodes.size() ); + { + // change element nodes + const SMDSAbs_EntityType geomType = anElem->GetEntityType(); + if ( geomType == SMDSEntity_Polyhedra ) + { + // special treatment for polyhedron + const SMDS_MeshVolume* aPolyhedron = SMDS_Mesh::DownCast< SMDS_MeshVolume >( anElem ); + if (!aPolyhedron) { + MESSAGE("Warning: bad volumic element"); + return false; + } + theMeshDS->ChangePolyhedronNodes( anElem, newNodes, aPolyhedron->GetQuantities() ); + } + else + // standard entity type + theMeshDS->ChangeElementNodes( anElem, &newNodes[ 0 ], newNodes.size() ); + } res = true; } @@ -10878,7 +11418,7 @@ namespace { \brief Identify the elements that will be affected by node duplication (actual duplication is not performed). This method is the first step of DoubleNodeElemGroupsInRegion. \param theElems - list of groups of elements (edges or faces) to be replicated - \param theNodesNot - list of groups of nodes not to replicated + \param theNodesNot - list of groups of nodes not to replicate \param theShape - shape to detect affected elements (element which geometric center located on or inside shape). If the shape is null, detection is done on faces orientations (select elements with a gravity center on the side given by faces normals). @@ -11020,7 +11560,7 @@ double SMESH_MeshEditor::OrientedAngle(const gp_Pnt& p0, const gp_Pnt& p1, const try { return n2.AngleWithRef(n1, vref); } - catch ( Standard_Failure ) { + catch ( Standard_Failure& ) { } return Max( v1.Magnitude(), v2.Magnitude() ); } @@ -11060,16 +11600,9 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector, DownIdCompare> faceDomains; // face --> (id domain --> id volume) - std::mapcelldom; // cell vtkId --> domain + std::map celldom; // cell vtkId --> domain std::map, DownIdCompare> cellDomains; // oldNode --> (id domain --> id cell) std::map > nodeDomains; // oldId --> (domainId --> newId) - faceDomains.clear(); - celldom.clear(); - cellDomains.clear(); - nodeDomains.clear(); - std::map emptyMap; - std::set emptySet; - emptyMap.clear(); //MESSAGE(".. Number of domains :"<GetVtkID(); + vtkIdType vtkId = anElem->GetVtkID(); //MESSAGE(" vtkId " << vtkId << " smdsId " << anElem->GetID()); int neighborsVtkIds[NBMAXNEIGHBORS]; int downIds[NBMAXNEIGHBORS]; @@ -11127,7 +11660,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorGetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId); for (int n = 0; n < nbNeighbors; n++) { - int smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]); + smIdType smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]); const SMDS_MeshElement* elem = meshDS->FindElement(smdsId); if (elem && ! domain.count(elem)) // neighbor is in another domain : face is shared { @@ -11179,14 +11712,13 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorfirst; //MESSAGE(" --- face " << face.cellId); std::set oldNodes; - oldNodes.clear(); grid->GetNodeIds(oldNodes, face.cellId, face.cellType); std::set::iterator itn = oldNodes.begin(); for (; itn != oldNodes.end(); ++itn) { int oldId = *itn; //MESSAGE(" node " << oldId); - vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId); + vtkCellLinks::Link l = (static_cast (grid->GetCellLinks()))->GetLink(oldId); for (int i=0; ifirst; //MESSAGE(" --- face " << face.cellId); std::set oldNodes; - oldNodes.clear(); grid->GetNodeIds(oldNodes, face.cellId, face.cellType); std::set::iterator itn = oldNodes.begin(); for (; itn != oldNodes.end(); ++itn) @@ -11295,7 +11826,6 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorfirst; //MESSAGE(" --- face " << face.cellId); std::set oldNodes; - oldNodes.clear(); grid->GetNodeIds(oldNodes, face.cellId, face.cellType); int nbMultipleNodes = 0; std::set::iterator itn = oldNodes.begin(); @@ -11356,7 +11886,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorFromVtkToSmds(vtkVolIds[ivol]); + smIdType smdsId = meshDS->FromVtkToSmds(vtkVolIds[ivol]); const SMDS_MeshElement* elem = meshDS->FindElement(smdsId); if (domain.count(elem)) { @@ -11365,7 +11895,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorGetID()); double values[3] = { 0,0,0 }; vtkIdType npts = 0; - vtkIdType* pts = 0; + vtkIdType const *pts(nullptr); grid->GetCellPoints(vtkVolIds[ivol], npts, pts); for ( vtkIdType i = 0; i < npts; ++i ) { @@ -11420,7 +11950,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector mapOfJunctionGroups; //MESSAGE(".. Creation of elements: simple junction"); - if (createJointElems) + if ( createJointElems ) { string joints2DName = "joints2D"; mapOfJunctionGroups[joints2DName] = this->myMesh->AddGroup(SMDSAbs_Face, joints2DName.c_str()); @@ -11435,15 +11965,14 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorfirst; std::set oldNodes; std::set::iterator itn; - oldNodes.clear(); grid->GetNodeIds(oldNodes, face.cellId, face.cellType); - std::map domvol = itface->second; + std::map domvol = itface->second; std::map::iterator itdom = domvol.begin(); - int dom1 = itdom->first; + int dom1 = itdom->first; int vtkVolId = itdom->second; itdom++; - int dom2 = itdom->first; + int dom2 = itdom->first; SMDS_MeshCell *vol = grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains, nodeQuadDomains); stringstream grpname; @@ -11500,7 +12029,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector, std::vector >::iterator ite = edgesMultiDomains.begin(); for (; ite != edgesMultiDomains.end(); ++ite) { - vector nodes = ite->first; + vector nodes = ite->first; vector orderDom = ite->second; vector orderedNodes; if (nodes.size() == 2) @@ -11537,10 +12066,9 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector, DownIdCompare> faceOrEdgeDom; // cellToModify --> (id domain --> id cell) std::map feDom; // vtk id of cell to modify --> id domain - faceOrEdgeDom.clear(); - feDom.clear(); //MESSAGE(".. Modification of elements"); + SMDSAbs_ElementType domainType = (*theElems[0].begin())->GetType(); for (int idomain = idom0; idomain < nbDomains; idomain++) { std::map >::const_iterator itnod = nodeDomains.begin(); @@ -11548,7 +12076,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorfirst; //MESSAGE(" node " << oldId); - vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId); + vtkCellLinks::Link l = (static_cast< vtkCellLinks *>(grid->GetCellLinks()))->GetLink(oldId); for (int i = 0; i < l.ncells; i++) { int vtkId = l.cells[i]; @@ -11558,13 +12086,29 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorGetParentVolumes(volParents, vtkId); + int nbvol = 0; + nbvol = grid->GetParentVolumes(volParents, vtkId); + if ( domainType == SMDSAbs_Volume ) + { + nbvol = grid->GetParentVolumes(volParents, vtkId); + } + else // domainType == SMDSAbs_Face + { + const int nbFaces = grid->getDownArray(vtkType)->getNumberOfUpCells(downId); + const int *upCells = grid->getDownArray(vtkType)->getUpCells(downId); + const unsigned char* upTypes = grid->getDownArray(vtkType)->getUpTypes(downId); + for (int i=0; i< nbFaces; i++) + { + int vtkFaceId = grid->getDownArray( upTypes[i] )->getVtkCellId(upCells[i]); + if (vtkFaceId >= 0) + volParents[nbvol++] = vtkFaceId; + } + } for (int j = 0; j < nbvol; j++) if (celldom.count(volParents[j]) && (celldom[volParents[j]] == idomain)) if (!feDom.count(vtkId)) { feDom[vtkId] = idomain; - faceOrEdgeDom[aCell] = emptyMap; faceOrEdgeDom[aCell][idomain] = vtkId; // affect face or edge to the first domain only //MESSAGE("affect cell " << this->GetMeshDS()->FromVtkToSmds(vtkId) << " domain " << idomain // << " type " << vtkType << " downId " << downId); @@ -11587,7 +12131,6 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorfirst; std::set oldNodes; std::set::iterator itn; - oldNodes.clear(); grid->GetNodeIds(oldNodes, face.cellId, face.cellType); //MESSAGE("examine cell, downId " << face.cellId << " type " << int(face.cellType)); std::map localClonedNodeIds; @@ -11654,10 +12197,7 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector clonedNodes; std::map intermediateNodes; - clonedNodes.clear(); - intermediateNodes.clear(); std::map mapOfJunctionGroups; - mapOfJunctionGroups.clear(); for ( size_t idom = 0; idom < theElems.size(); idom++ ) { @@ -11904,7 +12444,6 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, std::set setOfVolToCheck; std::vector gpnts; - gpnts.clear(); if (isNodeGroup) // --- a group of nodes is provided : find all the volumes using one or more of this nodes { @@ -11991,7 +12530,6 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, // Fill the group of inside volumes std::map mapOfNodeDistance2; - mapOfNodeDistance2.clear(); std::set setOfOutsideVol; while (!setOfVolToCheck.empty()) { @@ -12000,7 +12538,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, //MESSAGE("volume to check, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId)); bool volInside = false; vtkIdType npts = 0; - vtkIdType* pts = 0; + vtkIdType const *pts(nullptr); grid->GetCellPoints(vtkId, npts, pts); for (int i=0; i > shapeIdToVtkIdSet; // shapeId --> set of vtkId on skin - std::set emptySet; - emptySet.clear(); - std::set shapeIds; + std::set shapeIds; SMDS_ElemIteratorPtr itelem = sgrps->GetElements(); while (itelem->more()) @@ -12180,7 +12716,6 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, int vtkId = elem->GetVtkID(); if (!shapeIdToVtkIdSet.count(shapeId)) { - shapeIdToVtkIdSet[shapeId] = emptySet; shapeIds.insert(shapeId); } shapeIdToVtkIdSet[shapeId].insert(vtkId); @@ -12188,7 +12723,6 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, std::map > shapeIdToEdges; // shapeId --> set of downward edges std::set emptyEdges; - emptyEdges.clear(); std::map >::iterator itShape = shapeIdToVtkIdSet.begin(); for (; itShape != shapeIdToVtkIdSet.end(); ++itShape) @@ -12212,7 +12746,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, { if (neighborsVtkIds[n]<0) // only smds faces are considered as neighbors here continue; - int smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]); + smIdType smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]); const SMDS_MeshElement* elem = meshDS->FindElement(smdsId); if ( shapeIds.count(elem->getshapeId()) && !sgrps->Contains(elem)) // edge : neighbor in the set of shape, not in the group { @@ -12231,7 +12765,6 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, } std::list order; - order.clear(); if (nodesEdges.size() > 0) { order.push_back(nodesEdges[0]); //MESSAGE(" --- back " << order.back()+1); // SMDS id = VTK id + 1; @@ -12412,7 +12945,8 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, bool toCopyElements/*=false*/, bool toCopyExistingBoundary/*=false*/, bool toAddExistingBondary/*= false*/, - bool aroundElements/*= false*/) + bool aroundElements/*= false*/, + bool toCreateAllElements/*= false*/) { SMDSAbs_ElementType missType = (dimension == BND_2DFROM3D) ? SMDSAbs_Face : SMDSAbs_Edge; SMDSAbs_ElementType elemType = (dimension == BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume; @@ -12431,7 +12965,6 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, SMESH_MeshEditor* presentEditor; SMESH_MeshEditor tgtEditor2( tgtEditor.GetMesh() ); presentEditor = toAddExistingBondary ? &tgtEditor : &tgtEditor2; - SMESH_MesherHelper helper( *myMesh ); const TopAbs_ShapeEnum missShapeType = ( missType==SMDSAbs_Face ? TopAbs_FACE : TopAbs_EDGE ); SMDS_VolumeTool vTool; @@ -12469,8 +13002,9 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, const SMDS_MeshElement* otherVol = 0; for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ ) { - if ( !vTool.IsFreeFace(iface, &otherVol) && - ( !aroundElements || elements.count( otherVol ))) + if ( !toCreateAllElements && + !vTool.IsFreeFace(iface, &otherVol) && + ( !aroundElements || elements.count( otherVol ))) continue; freeFacets.push_back( iface ); } @@ -12567,8 +13101,8 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, for ( inode = 0; inode < srcNodes.size(); ++inode ) tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] ); if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( tgtNodes, - missType, - /*noMedium=*/false)) + missType, + /*noMedium=*/false)) continue; tgtEditor.AddElement( tgtNodes, elemKind.SetPoly( tgtNodes.size()/(iQuad+1) > 4 )); ++nbAddedBnd; @@ -12578,8 +13112,8 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, { TConnectivity& nodes = missingBndElems[ i ]; if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( nodes, - missType, - /*noMedium=*/false)) + missType, + /*noMedium=*/false)) continue; SMDS_MeshElement* newElem = tgtEditor.AddElement( nodes, elemKind.SetPoly( nodes.size()/(iQuad+1) > 4 ));