X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MeshEditor.cxx;h=9cc4d2378405173a2a3360dcedcb04904bf6e047;hp=8ca7653e074993ef57d109244060b7abaae480ca;hb=a0880e7c367025142b27c4669968a7611837c5a9;hpb=de00066f64e01e9028cc5bfc0390911a590a9428 diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 8ca7653e0..9cc4d2378 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -2975,7 +2975,6 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems, } AddToSameGroups( newElem1, elem, aMesh ); AddToSameGroups( newElem2, elem, aMesh ); - //aMesh->RemoveFreeElement(elem, aMesh->MeshElements(aShapeId), true); aMesh->RemoveElement( elem ); } @@ -4817,7 +4816,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, else if(nbSame==1) { // ---> pyramid + pentahedron - can not be created since it is needed // additional middle node at the center of face - INFOS( " Sweep for face " << elem->GetID() << " can not be created" ); + //INFOS( " Sweep for face " << elem->GetID() << " can not be created" ); return; } else if( nbSame == 2 ) { @@ -5003,16 +5002,19 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, SMDSAbs_ElementType highType = SMDSAbs_Edge; // count most complex elements only while ( eIt->more() && nbInitElems < 2 ) { const SMDS_MeshElement* e = eIt->next(); - SMDSAbs_ElementType type = e->GetType(); - if ( type == SMDSAbs_Volume || type < highType ) continue; + SMDSAbs_ElementType type = e->GetType(); + if ( type == SMDSAbs_Volume || + type < highType || + !elemSet.count(e)) + continue; if ( type > highType ) { nbInitElems = 0; - highType = type; + highType = type; } el = e; - nbInitElems += elemSet.count(el); + ++nbInitElems; } - if ( nbInitElems < 2 ) { + if ( nbInitElems == 1 ) { bool NotCreateEdge = el && el->IsMediumNode(node); if(!NotCreateEdge) { vector newNodesItVec( 1, nList ); @@ -5356,8 +5358,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, SMDS_MeshCell::interlacedSmdsOrder( elem->GetEntityType(), nbn ); SMDS_MeshCell::applyInterlaceRev( interlace, nodeVec ); - if ( const SMDS_MeshElement* face = AddElement( nodeVec, anyFace.Init( elem ))) - myLastCreatedElems.Append( face ); + AddElement( nodeVec, anyFace.Init( elem )); while ( srcElements.Length() < myLastCreatedElems.Length() ) srcElements.Append( elem ); @@ -6388,7 +6389,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], SMESH_MeshEditor_PathPoint PP2 = currList.front(); gp_Dir D1 = PP1.Tangent(); gp_Dir D2 = PP2.Tangent(); - gp_Dir Dnew( ( D1.XYZ() + D2.XYZ() ) / 2 ); + gp_Dir Dnew( D1.XYZ() + D2.XYZ() ); PP1.SetTangent(Dnew); fullList.push_back(PP1); fullList.splice( fullList.end(), currList, ++currList.begin(), currList.end() ); @@ -6453,7 +6454,7 @@ SMESH_MeshEditor::MakeEdgePathPoints(std::list& aPrms, aL2 = aVec.SquareMagnitude(); if ( aL2 < aTolVec2 ) return EXTR_CANT_GET_TANGENT; - gp_Dir aTgt( aVec ); + gp_Dir aTgt( FirstIsStart ? aVec : -aVec ); aPP.SetPnt( aP3D ); aPP.SetTangent( aTgt ); aPP.SetParameter( aT ); @@ -6478,9 +6479,11 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets const bool theMakeGroups) { const int aNbTP = fullList.size(); + // Angles if( theHasAngles && !theAngles.empty() && theLinearVariation ) LinearAngleVariation(aNbTP-1, theAngles); + // fill vector of path points with angles vector aPPs; list::iterator itPP = fullList.begin(); @@ -6510,10 +6513,10 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets { TIDSortedElemSet& theElements = theElemSets[ is2ndSet ]; itElem = theElements.begin(); - for ( ; itElem != theElements.end(); itElem++ ) { + for ( ; itElem != theElements.end(); itElem++ ) + { const SMDS_MeshElement* elem = *itElem; - - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); while ( itN->more() ) { const SMDS_MeshElement* node = itN->next(); if ( newNodes.insert( node ).second ) @@ -6527,19 +6530,15 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets // 4. Processing the elements SMESHDS_Mesh* aMesh = GetMeshDS(); + list emptyList; setElemsFirst( theElemSets ); for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet ) { TIDSortedElemSet& theElements = theElemSets[ is2ndSet ]; - for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ ) { - // check element type + for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ ) + { const SMDS_MeshElement* elem = *itElem; - if ( !elem ) - continue; - // SMDSAbs_ElementType aTypeE = elem->GetType(); - // if ( aTypeE != SMDSAbs_Face && aTypeE != SMDSAbs_Edge ) - // continue; vector & newNodesItVec = mapElemNewNodes[ elem ]; newNodesItVec.reserve( elem->NbNodes() ); @@ -6551,13 +6550,11 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets { ++nodeIndex; // check if a node has been already processed - const SMDS_MeshNode* node = - static_cast( itN->next() ); - TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node ); - if ( nIt == mapNewNodes.end() ) { - nIt = mapNewNodes.insert( make_pair( node, list() )).first; - list& listNewNodes = nIt->second; - + const SMDS_MeshNode* node = cast2Node( itN->next() ); + TNodeOfNodeListMap::iterator nIt = mapNewNodes.insert( make_pair( node, emptyList )).first; + list& listNewNodes = nIt->second; + if ( listNewNodes.empty() ) + { // make new nodes Standard_Real aAngle1x, aAngleT1T0, aTolAng; gp_Pnt aP0x, aP1x, aPN0, aPN1, aV0x, aV1x; @@ -6572,7 +6569,6 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0]; aP0x = aPP0.Pnt(); aDT0x= aPP0.Tangent(); - //cout<<"j = 0 PP: Pnt("< aTolAng) { + if (fabs(aAngleT1T0) > aTolAng) + { aDT1T0=aDT1x^aDT0x; anAxT1T0.SetLocation( aV1x ); anAxT1T0.SetDirection( aDT1T0 ); @@ -6610,13 +6607,11 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets } // make new node - //MESSAGE("elem->IsQuadratic " << elem->IsQuadratic() << " " << elem->IsMediumNode(node)); - if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) { + if ( elem->IsQuadratic() && !elem->IsMediumNode(node) ) + { // create additional node - double x = ( aPN1.X() + aPN0.X() )/2.; - double y = ( aPN1.Y() + aPN0.Y() )/2.; - double z = ( aPN1.Z() + aPN0.Z() )/2.; - const SMDS_MeshNode* newNode = aMesh->AddNode(x,y,z); + gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() ); + const SMDS_MeshNode* newNode = aMesh->AddNode( midP.X(), midP.Y(), midP.Z() ); myLastCreatedNodes.Append(newNode); srcNodes.Append( node ); listNewNodes.push_back( newNode ); @@ -6632,42 +6627,40 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet theElemSets aDT0x = aDT1x; } } - - else { + else if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) + { // if current elem is quadratic and current node is not medium // we have to check - may be it is needed to insert additional nodes - if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) { - list< const SMDS_MeshNode* > & listNewNodes = nIt->second; - if(listNewNodes.size()==aNbTP-1) { - vector aNodes(2*(aNbTP-1)); - gp_XYZ P(node->X(), node->Y(), node->Z()); - list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin(); - int i; - for(i=0; iX() + P.X() )/2.; - double y = ( N->Y() + P.Y() )/2.; - double z = ( N->Z() + P.Z() )/2.; - const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z); - srcNodes.Append( node ); - myLastCreatedNodes.Append(newN); - aNodes[2*i] = newN; - aNodes[2*i+1] = N; - P = gp_XYZ(N->X(),N->Y(),N->Z()); - } - listNewNodes.clear(); - for(i=0; i<2*(aNbTP-1); i++) { - listNewNodes.push_back(aNodes[i]); - } + list< const SMDS_MeshNode* > & listNewNodes = nIt->second; + if ( listNewNodes.size() == aNbTP-1 ) + { + vector aNodes(2*(aNbTP-1)); + gp_XYZ P(node->X(), node->Y(), node->Z()); + list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin(); + int i; + for(i=0; iX() + P.X() )/2.; + double y = ( N->Y() + P.Y() )/2.; + double z = ( N->Z() + P.Z() )/2.; + const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z); + srcNodes.Append( node ); + myLastCreatedNodes.Append(newN); + aNodes[2*i] = newN; + aNodes[2*i+1] = N; + P = gp_XYZ(N->X(),N->Y(),N->Z()); + } + listNewNodes.clear(); + for(i=0; i<2*(aNbTP-1); i++) { + listNewNodes.push_back(aNodes[i]); } } } newNodesItVec.push_back( nIt ); } + // make new elements - //sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], - // newNodesItVec[0]->second.size(), myLastCreatedElems ); sweepElement( elem, newNodesItVec, newElemsMap[elem], aNbTP-1, srcElems ); } } @@ -7246,19 +7239,17 @@ int SMESH_MeshEditor::SimplifyFace (const vector& faceNod set nodeSet; // get simple seq of nodes - //const SMDS_MeshNode* simpleNodes[ nbNodes ]; vector simpleNodes( nbNodes ); - int iSimple = 0, nbUnique = 0; + int iSimple = 0; simpleNodes[iSimple++] = faceNodes[0]; - nbUnique++; for (int iCur = 1; iCur < nbNodes; iCur++) { if (faceNodes[iCur] != simpleNodes[iSimple - 1]) { simpleNodes[iSimple++] = faceNodes[iCur]; - if (nodeSet.insert( faceNodes[iCur] ).second) - nbUnique++; + nodeSet.insert( faceNodes[iCur] ); } } + int nbUnique = nodeSet.size(); int nbSimple = iSimple; if (simpleNodes[nbSimple - 1] == simpleNodes[0]) { nbSimple--; @@ -7372,8 +7363,8 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) for ( ; eIt != elems.end(); eIt++ ) { const SMDS_MeshElement* elem = *eIt; - int nbNodes = elem->NbNodes(); - int aShapeId = FindShape( elem ); + const int nbNodes = elem->NbNodes(); + const int aShapeId = FindShape( elem ); nodeSet.clear(); curNodes.resize( nbNodes ); @@ -7458,6 +7449,8 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, nbNewNodes ), face_nodes ); } + elemType.SetPoly(( nbNewNodes / ( elemType.myIsQuad + 1 ) > 4 )); + SMDS_MeshElement* newElem = AddElement( face_nodes, elemType ); if ( aShapeId ) aMesh->SetMeshElementOnShape(newElem, aShapeId); @@ -7474,9 +7467,9 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) } else { // each face has to be analyzed in order to check volume validity - const SMDS_VtkVolume* aPolyedre = - dynamic_cast( elem ); - if (aPolyedre) { + const SMDS_VtkVolume* aPolyedre = dynamic_cast( elem ); + if (aPolyedre) + { int nbFaces = aPolyedre->NbFaces(); vector poly_nodes; @@ -7504,7 +7497,6 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) if (quantities.size() > 3) { - //aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities); const SMDS_MeshElement* newElem = aMesh->AddPolyhedralVolume(poly_nodes, quantities); myLastCreatedElems.Append(newElem); @@ -7912,17 +7904,21 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) if ( isOk ) // the non-poly elem remains valid after sticking nodes { - elemType.Init( elem ).SetID( elem->GetID() ); + if ( nbNodes != nbUniqueNodes || + !aMesh->ChangeElementNodes( elem, & curNodes[0], nbNodes )) + { + elemType.Init( elem ).SetID( elem->GetID() ); - SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0; - aMesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false); + SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0; + aMesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false); - uniqueNodes.resize(nbUniqueNodes); - SMDS_MeshElement* newElem = this->AddElement( uniqueNodes, elemType ); - if ( sm && newElem ) - sm->AddElement( newElem ); - if ( elem != newElem ) - ReplaceElemInGroups( elem, newElem, aMesh ); + uniqueNodes.resize(nbUniqueNodes); + SMDS_MeshElement* newElem = this->AddElement( uniqueNodes, elemType ); + if ( sm && newElem ) + sm->AddElement( newElem ); + if ( elem != newElem ) + ReplaceElemInGroups( elem, newElem, aMesh ); + } } else { // Remove invalid regular element or invalid polygon @@ -7959,10 +7955,6 @@ public: const SMDS_MeshElement* Get() const { return myElem; } - void Set(const SMDS_MeshElement* e) const - { myElem = e; } - - private: mutable const SMDS_MeshElement* myElem; }; @@ -8090,6 +8082,24 @@ static const SMDS_MeshElement* findAdjacentFace(const SMDS_MeshNode* n1, return SMESH_MeshAlgos::FindFaceInSet( n1, n2, elemSet, avoidSet ); } +//======================================================================= +//function : findSegment +//purpose : Return a mesh segment by two nodes one of which can be medium +//======================================================================= + +static const SMDS_MeshElement* findSegment(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2) +{ + SMDS_ElemIteratorPtr it = n1->GetInverseElementIterator( SMDSAbs_Edge ); + while ( it->more() ) + { + const SMDS_MeshElement* seg = it->next(); + if ( seg->GetNodeIndex( n2 ) >= 0 ) + return seg; + } + return 0; +} + //======================================================================= //function : FindFreeBorder //purpose : @@ -8114,7 +8124,6 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirst theNodes.push_back( theFirstNode ); theNodes.push_back( theSecondNode ); - //vector nodes; const SMDS_MeshNode *nIgnore = theFirstNode, *nStart = theSecondNode; TIDSortedElemSet foundElems; bool needTheLast = ( theLastNode != 0 ); @@ -8126,17 +8135,16 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirst // find all free border faces sharing form nStart list< const SMDS_MeshElement* > curElemList; - list< const SMDS_MeshNode* > nStartList; + list< const SMDS_MeshNode* > nStartList; SMDS_ElemIteratorPtr invElemIt = nStart->GetInverseElementIterator(SMDSAbs_Face); while ( invElemIt->more() ) { const SMDS_MeshElement* e = invElemIt->next(); if ( e == curElem || foundElems.insert( e ).second ) { // get nodes int iNode = 0, nbNodes = e->NbNodes(); - //const SMDS_MeshNode* nodes[nbNodes+1]; vector nodes(nbNodes+1); - if(e->IsQuadratic()) { + if ( e->IsQuadratic() ) { const SMDS_VtkFace* F = dynamic_cast(e); if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); @@ -8253,6 +8261,8 @@ bool SMESH_MeshEditor::CheckFreeBorderNodes(const SMDS_MeshNode* theNode1, //======================================================================= //function : SewFreeBorder //purpose : +//warning : for border-to-side sewing theSideSecondNode is considered as +// the last side node and theSideThirdNode is not used //======================================================================= SMESH_MeshEditor::Sew_Error @@ -8276,9 +8286,9 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, // find side nodes and elements // ==================================== - list< const SMDS_MeshNode* > nSide[ 2 ]; + list< const SMDS_MeshNode* > nSide[ 2 ]; list< const SMDS_MeshElement* > eSide[ 2 ]; - list< const SMDS_MeshNode* >::iterator nIt[ 2 ]; + list< const SMDS_MeshNode* >::iterator nIt[ 2 ]; list< const SMDS_MeshElement* >::iterator eIt[ 2 ]; // Free border 1 @@ -8517,9 +8527,23 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, int nbNodes[] = { nSide[0].size(), nSide[1].size() }; int maxNbNodes = Max( nbNodes[0], nbNodes[1] ); + bool toMergeConformal = ( nbNodes[0] == nbNodes[1] ); + if ( toMergeConformal && toCreatePolygons ) + { + // do not merge quadrangles if polygons are OK (IPAL0052824) + eIt[0] = eSide[0].begin(); + eIt[1] = eSide[1].begin(); + bool allQuads[2] = { true, true }; + for ( int iBord = 0; iBord < 2; iBord++ ) { // loop on 2 borders + for ( ; allQuads[iBord] && eIt[iBord] != eSide[iBord].end(); ++eIt[iBord] ) + allQuads[iBord] = ( (*eIt[iBord])->NbCornerNodes() == 4 ); + } + toMergeConformal = ( !allQuads[0] && !allQuads[1] ); + } + TListOfListOfNodes nodeGroupsToMerge; - if ( nbNodes[0] == nbNodes[1] || - ( theSideIsFreeBorder && !theSideThirdNode)) { + if (( toMergeConformal ) || + ( theSideIsFreeBorder && !theSideThirdNode )) { // all nodes are to be merged @@ -8537,10 +8561,9 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, // insert new nodes into the border and the side to get equal nb of segments // get normalized parameters of nodes on the borders - //double param[ 2 ][ maxNbNodes ]; - double* param[ 2 ]; - param[0] = new double [ maxNbNodes ]; - param[1] = new double [ maxNbNodes ]; + vector< double > param[ 2 ]; + param[0].resize( maxNbNodes ); + param[1].resize( maxNbNodes ); int iNode, iBord; for ( iBord = 0; iBord < 2; iBord++ ) { // loop on 2 borders list< const SMDS_MeshNode* >& nodes = nSide[ iBord ]; @@ -8585,8 +8608,8 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, if ( i[ iBord ] > 0 ) prevParam = Max( prevParam, param[iBord][ i[iBord] - 1 ]); } - double minParam = Min( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]); - double maxParam = Max( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]); + double minParam = Min( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]); + double maxParam = Max( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]); double minSegLen = Min( nextParam - minParam, maxParam - prevParam ); // choose to insert or to merge nodes @@ -8610,10 +8633,10 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, // insert // ------ int intoBord = ( du < 0 ) ? 0 : 1; - const SMDS_MeshElement* elem = *eIt[ intoBord ]; + const SMDS_MeshElement* elem = *eIt [ intoBord ]; const SMDS_MeshNode* n1 = nPrev[ intoBord ]; - const SMDS_MeshNode* n2 = *nIt[ intoBord ]; - const SMDS_MeshNode* nIns = *nIt[ 1 - intoBord ]; + const SMDS_MeshNode* n2 = *nIt [ intoBord ]; + const SMDS_MeshNode* nIns = *nIt [ 1 - intoBord ]; if ( intoBord == 1 ) { // move node of the border to be on a link of elem of the side gp_XYZ p1 (n1->X(), n1->Y(), n1->Z()); @@ -8623,7 +8646,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, GetMeshDS()->MoveNode( nIns, p.X(), p.Y(), p.Z() ); } insertMapIt = insertMap.find( elem ); - bool notFound = ( insertMapIt == insertMap.end() ); + bool notFound = ( insertMapIt == insertMap.end() ); bool otherLink = ( !notFound && (*insertMapIt).second.front() != n1 ); if ( otherLink ) { // insert into another link of the same element: @@ -8633,12 +8656,11 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, const SMDS_MeshNode* n22 = nodeList.front(); nodeList.pop_front(); InsertNodesIntoLink( elem, n12, n22, nodeList, toCreatePolygons ); // 2. perform insertion into the link of adjacent faces - while (true) { - const SMDS_MeshElement* adjElem = findAdjacentFace( n12, n22, elem ); - if ( adjElem ) - InsertNodesIntoLink( adjElem, n12, n22, nodeList, toCreatePolygons ); - else - break; + while ( const SMDS_MeshElement* adjElem = findAdjacentFace( n12, n22, elem )) { + InsertNodesIntoLink( adjElem, n12, n22, nodeList, toCreatePolygons ); + } + while ( const SMDS_MeshElement* seg = findSegment( n12, n22 )) { + InsertNodesIntoLink( seg, n12, n22, nodeList ); } if (toCreatePolyedrs) { // perform insertion into the links of adjacent volumes @@ -8650,8 +8672,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, } if ( notFound || otherLink ) { // add element and nodes of the side into the insertMap - insertMapIt = insertMap.insert - ( TElemOfNodeListMap::value_type( elem, list() )).first; + insertMapIt = insertMap.insert( make_pair( elem, list() )).first; (*insertMapIt).second.push_back( n1 ); (*insertMapIt).second.push_back( n2 ); } @@ -8685,14 +8706,14 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, InsertNodesIntoLink( elem, n1, n2, nodeList, toCreatePolygons ); + while ( const SMDS_MeshElement* seg = findSegment( n1, n2 )) { + InsertNodesIntoLink( seg, n1, n2, nodeList ); + } + if ( !theSideIsFreeBorder ) { // look for and insert nodes into the faces adjacent to elem - while (true) { - const SMDS_MeshElement* adjElem = findAdjacentFace( n1, n2, elem ); - if ( adjElem ) - InsertNodesIntoLink( adjElem, n1, n2, nodeList, toCreatePolygons ); - else - break; + while ( const SMDS_MeshElement* adjElem = findAdjacentFace( n1, n2, elem )) { + InsertNodesIntoLink( adjElem, n1, n2, nodeList, toCreatePolygons ); } } if (toCreatePolyedrs) { @@ -8700,69 +8721,155 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, UpdateVolumes(n1, n2, nodeList); } } - - delete param[0]; - delete param[1]; } // end: insert new nodes MergeNodes ( nodeGroupsToMerge ); + + // Remove coincident segments + + // get new segments + TIDSortedElemSet segments; + SMESH_SequenceOfElemPtr newFaces; + for ( int i = 1; i <= myLastCreatedElems.Length(); ++i ) + { + if ( !myLastCreatedElems(i) ) continue; + if ( myLastCreatedElems(i)->GetType() == SMDSAbs_Edge ) + segments.insert( segments.end(), myLastCreatedElems(i) ); + else + newFaces.Append( myLastCreatedElems(i) ); + } + // get segments adjacent to merged nodes + TListOfListOfNodes::iterator groupIt = nodeGroupsToMerge.begin(); + for ( ; groupIt != nodeGroupsToMerge.end(); groupIt++ ) + { + const list& nodes = *groupIt; + SMDS_ElemIteratorPtr segIt = nodes.front()->GetInverseElementIterator( SMDSAbs_Edge ); + while ( segIt->more() ) + segments.insert( segIt->next() ); + } + + // find coincident + TListOfListOfElementsID equalGroups; + if ( !segments.empty() ) + FindEqualElements( segments, equalGroups ); + if ( !equalGroups.empty() ) + { + // remove from segments those that will be removed + TListOfListOfElementsID::iterator itGroups = equalGroups.begin(); + for ( ; itGroups != equalGroups.end(); ++itGroups ) + { + list< int >& group = *itGroups; + list< int >::iterator id = group.begin(); + for ( ++id; id != group.end(); ++id ) + if ( const SMDS_MeshElement* seg = GetMeshDS()->FindElement( *id )) + segments.erase( seg ); + } + // remove equal segments + MergeElements( equalGroups ); + + // restore myLastCreatedElems + myLastCreatedElems = newFaces; + TIDSortedElemSet::iterator seg = segments.begin(); + for ( ; seg != segments.end(); ++seg ) + myLastCreatedElems.Append( *seg ); + } + return aResult; } //======================================================================= //function : InsertNodesIntoLink -//purpose : insert theNodesToInsert into theFace between theBetweenNode1 +//purpose : insert theNodesToInsert into theElement between theBetweenNode1 // and theBetweenNode2 and split theElement //======================================================================= -void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, +void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theElement, const SMDS_MeshNode* theBetweenNode1, const SMDS_MeshNode* theBetweenNode2, list& theNodesToInsert, const bool toCreatePoly) { + if ( !theElement ) return; + + SMESHDS_Mesh *aMesh = GetMeshDS(); + vector newElems; + + if ( theElement->GetType() == SMDSAbs_Edge ) + { + theNodesToInsert.push_front( theBetweenNode1 ); + theNodesToInsert.push_back ( theBetweenNode2 ); + list::iterator n = theNodesToInsert.begin(); + const SMDS_MeshNode* n1 = *n; + for ( ++n; n != theNodesToInsert.end(); ++n ) + { + const SMDS_MeshNode* n2 = *n; + if ( const SMDS_MeshElement* seg = aMesh->FindEdge( n1, n2 )) + AddToSameGroups( seg, theElement, aMesh ); + else + newElems.push_back( aMesh->AddEdge ( n1, n2 )); + n1 = n2; + } + theNodesToInsert.pop_front(); + theNodesToInsert.pop_back(); + + if ( theElement->IsQuadratic() ) // add a not split part + { + vector nodes( theElement->begin_nodes(), + theElement->end_nodes() ); + int iOther = 0, nbN = nodes.size(); + for ( ; iOther < nbN; ++iOther ) + if ( nodes[iOther] != theBetweenNode1 && + nodes[iOther] != theBetweenNode2 ) + break; + if ( iOther == 0 ) + { + if ( const SMDS_MeshElement* seg = aMesh->FindEdge( nodes[0], nodes[1] )) + AddToSameGroups( seg, theElement, aMesh ); + else + newElems.push_back( aMesh->AddEdge ( nodes[0], nodes[1] )); + } + else if ( iOther == 2 ) + { + if ( const SMDS_MeshElement* seg = aMesh->FindEdge( nodes[1], nodes[2] )) + AddToSameGroups( seg, theElement, aMesh ); + else + newElems.push_back( aMesh->AddEdge ( nodes[1], nodes[2] )); + } + } + // treat new elements + for ( size_t i = 0; i < newElems.size(); ++i ) + if ( newElems[i] ) + { + aMesh->SetMeshElementOnShape( newElems[i], theElement->getshapeId() ); + myLastCreatedElems.Append( newElems[i] ); + } + ReplaceElemInGroups( theElement, newElems, aMesh ); + aMesh->RemoveElement( theElement ); + return; + + } // if ( theElement->GetType() == SMDSAbs_Edge ) + + const SMDS_MeshElement* theFace = theElement; if ( theFace->GetType() != SMDSAbs_Face ) return; // find indices of 2 link nodes and of the rest nodes int iNode = 0, il1, il2, i3, i4; il1 = il2 = i3 = i4 = -1; - //const SMDS_MeshNode* nodes[ theFace->NbNodes() ]; vector nodes( theFace->NbNodes() ); - if(theFace->IsQuadratic()) { - const SMDS_VtkFace* F = - dynamic_cast(theFace); - if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); - // use special nodes iterator - SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); - while( anIter->more() ) { - const SMDS_MeshNode* n = cast2Node(anIter->next()); - if ( n == theBetweenNode1 ) - il1 = iNode; - else if ( n == theBetweenNode2 ) - il2 = iNode; - else if ( i3 < 0 ) - i3 = iNode; - else - i4 = iNode; - nodes[ iNode++ ] = n; - } - } - else { - SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator(); - while ( nodeIt->more() ) { - const SMDS_MeshNode* n = static_cast( nodeIt->next() ); - if ( n == theBetweenNode1 ) - il1 = iNode; - else if ( n == theBetweenNode2 ) - il2 = iNode; - else if ( i3 < 0 ) - i3 = iNode; - else - i4 = iNode; - nodes[ iNode++ ] = n; - } + SMDS_NodeIteratorPtr nodeIt = theFace->interlacedNodesIterator(); + while ( nodeIt->more() ) { + const SMDS_MeshNode* n = nodeIt->next(); + if ( n == theBetweenNode1 ) + il1 = iNode; + else if ( n == theBetweenNode2 ) + il2 = iNode; + else if ( i3 < 0 ) + i3 = iNode; + else + i4 = iNode; + nodes[ iNode++ ] = n; } if ( il1 < 0 || il2 < 0 || i3 < 0 ) return ; @@ -8792,9 +8899,8 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, // add nodes of face up to first node of link bool isFLN = false; - if(theFace->IsQuadratic()) { - const SMDS_VtkFace* F = - dynamic_cast(theFace); + if ( theFace->IsQuadratic() ) { + const SMDS_VtkFace* F = dynamic_cast(theFace); if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); // use special nodes iterator SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); @@ -8836,28 +8942,12 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, } } - // edit or replace the face - SMESHDS_Mesh *aMesh = GetMeshDS(); - - if (theFace->IsPoly()) { - aMesh->ChangePolygonNodes(theFace, poly_nodes); - } - else { - int aShapeId = FindShape( theFace ); - - SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); - - aMesh->RemoveElement(theFace); - } - return; + // make a new face + newElems.push_back( aMesh->AddPolygonalFace( poly_nodes )); } - SMESHDS_Mesh *aMesh = GetMeshDS(); - if( !theFace->IsQuadratic() ) { - + else if ( !theFace->IsQuadratic() ) + { // put aNodesToInsert between theBetweenNode1 and theBetweenNode2 int nbLinkNodes = 2 + aNodesToInsert.size(); //const SMDS_MeshNode* linkNodes[ nbLinkNodes ]; @@ -8906,41 +8996,32 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, } // create new elements - int aShapeId = FindShape( theFace ); - i1 = 0; i2 = 1; for ( iSplit = 0; iSplit < nbSplits - 1; iSplit++ ) { SMDS_MeshElement* newElem = 0; if ( iSplit == iBestQuad ) - newElem = aMesh->AddFace (linkNodes[ i1++ ], - linkNodes[ i2++ ], - nodes[ i3 ], - nodes[ i4 ]); + newElems.push_back( aMesh->AddFace (linkNodes[ i1++ ], + linkNodes[ i2++ ], + nodes[ i3 ], + nodes[ i4 ])); else - newElem = aMesh->AddFace (linkNodes[ i1++ ], - linkNodes[ i2++ ], - nodes[ iSplit < iBestQuad ? i4 : i3 ]); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); + newElems.push_back( aMesh->AddFace (linkNodes[ i1++ ], + linkNodes[ i2++ ], + nodes[ iSplit < iBestQuad ? i4 : i3 ])); } - // change nodes of theFace const SMDS_MeshNode* newNodes[ 4 ]; newNodes[ 0 ] = linkNodes[ i1 ]; newNodes[ 1 ] = linkNodes[ i2 ]; newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ]; newNodes[ 3 ] = nodes[ i4 ]; - //aMesh->ChangeElementNodes( theFace, newNodes, iSplit == iBestQuad ? 4 : 3 ); - const SMDS_MeshElement* newElem = 0; if (iSplit == iBestQuad) - newElem = aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] ); + newElems.push_back( aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] )); else - newElem = aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] ); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); -} // end if(!theFace->IsQuadratic()) + newElems.push_back( aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] )); + + } // end if(!theFace->IsQuadratic()) + else { // theFace is quadratic // we have to split theFace on simple triangles and one simple quadrangle int tmp = il1/2; @@ -8967,66 +9048,38 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, // n4 n6 n5 n4 // create new elements - int aShapeId = FindShape( theFace ); - int n1,n2,n3; - if(nbFaceNodes==6) { // quadratic triangle - SMDS_MeshElement* newElem = - aMesh->AddFace(nodes[3],nodes[4],nodes[5]); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); - if(theFace->IsMediumNode(nodes[il1])) { + if ( nbFaceNodes == 6 ) { // quadratic triangle + newElems.push_back( aMesh->AddFace( nodes[3], nodes[4], nodes[5] )); + if ( theFace->IsMediumNode(nodes[il1]) ) { // create quadrangle - newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[5]); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); + newElems.push_back( aMesh->AddFace( nodes[0], nodes[1], nodes[3], nodes[5] )); n1 = 1; n2 = 2; n3 = 3; } else { // create quadrangle - newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[5]); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); + newElems.push_back( aMesh->AddFace( nodes[1], nodes[2], nodes[3], nodes[5] )); n1 = 0; n2 = 1; n3 = 5; } } else { // nbFaceNodes==8 - quadratic quadrangle - SMDS_MeshElement* newElem = - aMesh->AddFace(nodes[3],nodes[4],nodes[5]); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); - newElem = aMesh->AddFace(nodes[5],nodes[6],nodes[7]); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); - newElem = aMesh->AddFace(nodes[5],nodes[7],nodes[3]); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); - if(theFace->IsMediumNode(nodes[il1])) { + newElems.push_back( aMesh->AddFace( nodes[3], nodes[4], nodes[5] )); + newElems.push_back( aMesh->AddFace( nodes[5], nodes[6], nodes[7] )); + newElems.push_back( aMesh->AddFace( nodes[5], nodes[7], nodes[3] )); + if ( theFace->IsMediumNode( nodes[ il1 ])) { // create quadrangle - newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[7]); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); + newElems.push_back( aMesh->AddFace( nodes[0], nodes[1], nodes[3], nodes[7] )); n1 = 1; n2 = 2; n3 = 3; } else { // create quadrangle - newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[7]); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); + newElems.push_back( aMesh->AddFace( nodes[1], nodes[2], nodes[3], nodes[7] )); n1 = 0; n2 = 1; n3 = 7; @@ -9034,30 +9087,34 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, } // create needed triangles using n1,n2,n3 and inserted nodes int nbn = 2 + aNodesToInsert.size(); - //const SMDS_MeshNode* aNodes[nbn]; vector aNodes(nbn); - aNodes[0] = nodes[n1]; + aNodes[0 ] = nodes[n1]; aNodes[nbn-1] = nodes[n2]; list::iterator nIt = aNodesToInsert.begin(); for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) { aNodes[iNode++] = *nIt; } - for(i=1; iAddFace(aNodes[i-1],aNodes[i],nodes[n3]); - myLastCreatedElems.Append(newElem); - if ( aShapeId && newElem ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); - } + for ( i = 1; i < nbn; i++ ) + newElems.push_back( aMesh->AddFace( aNodes[i-1], aNodes[i], nodes[n3] )); } - // remove old face + + // remove the old face + for ( size_t i = 0; i < newElems.size(); ++i ) + if ( newElems[i] ) + { + aMesh->SetMeshElementOnShape( newElems[i], theFace->getshapeId() ); + myLastCreatedElems.Append( newElems[i] ); + } + ReplaceElemInGroups( theFace, newElems, aMesh ); aMesh->RemoveElement(theFace); -} + +} // InsertNodesIntoLink() //======================================================================= //function : UpdateVolumes //purpose : //======================================================================= + void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode1, const SMDS_MeshNode* theBetweenNode2, list& theNodesToInsert) @@ -9119,24 +9176,16 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode quantities[iface] = nbFaceNodes + nbInserted; } - // Replace or update the volume + // Replace the volume SMESHDS_Mesh *aMesh = GetMeshDS(); - if (elem->IsPoly()) { - aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities); - - } - else { - int aShapeId = FindShape( elem ); - - SMDS_MeshElement* newElem = - aMesh->AddPolyhedralVolume(poly_nodes, quantities); - myLastCreatedElems.Append(newElem); - if (aShapeId && newElem) - aMesh->SetMeshElementOnShape(newElem, aShapeId); - - aMesh->RemoveElement(elem); + if ( SMDS_MeshElement* newElem = aMesh->AddPolyhedralVolume( poly_nodes, quantities )) + { + aMesh->SetMeshElementOnShape( newElem, elem->getshapeId() ); + myLastCreatedElems.Append( newElem ); + ReplaceElemInGroups( elem, newElem, aMesh ); } + aMesh->RemoveElement( elem ); } } @@ -11609,7 +11658,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector TConnectivity; TConnectivity tgtNodes; - ElemFeatures elemKind( missType ); + ElemFeatures elemKind( missType ), elemToCopy; + + vector presentBndElems; + vector missingBndElems; + vector freeFacets; + TConnectivity nodes, elemNodes; SMDS_ElemIteratorPtr eIt; if (elements.empty()) eIt = aMesh->elementsIterator(elemType); @@ -12546,18 +12600,24 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, // ------------------------------------------------------------------------------------ // 1. For an elem, get present bnd elements and connectivities of missing bnd elements // ------------------------------------------------------------------------------------ - vector presentBndElems; - vector missingBndElems; - TConnectivity nodes, elemNodes; + presentBndElems.clear(); + missingBndElems.clear(); + freeFacets.clear(); nodes.clear(); elemNodes.clear(); if ( vTool.Set(elem, /*ignoreCentralNodes=*/true) ) // elem is a volume -------------- { - vTool.SetExternalNormal(); const SMDS_MeshElement* otherVol = 0; for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ ) { if ( !vTool.IsFreeFace(iface, &otherVol) && ( !aroundElements || elements.count( otherVol ))) continue; + freeFacets.push_back( iface ); + } + if ( missType == SMDSAbs_Face ) + vTool.SetExternalNormal(); + for ( size_t i = 0; i < freeFacets.size(); ++i ) + { + int iface = freeFacets[i]; const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface); const size_t nbFaceNodes = vTool.NbFaceNodes (iface); if ( missType == SMDSAbs_Edge ) // boundary edges @@ -12566,9 +12626,9 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, for ( int i = 0; i < nbFaceNodes; i += 1+iQuad) { for ( int j = 0; j < nodes.size(); ++j ) - nodes[j] =nn[i+j]; + nodes[j] = nn[ i+j ]; if ( const SMDS_MeshElement* edge = - aMesh->FindElement(nodes,SMDSAbs_Edge,/*noMedium=*/false)) + aMesh->FindElement( nodes, SMDSAbs_Edge, /*noMedium=*/false )) presentBndElems.push_back( edge ); else missingBndElems.push_back( nodes ); @@ -12703,7 +12763,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, tgtNodes.resize( e->NbNodes() ); for ( inode = 0; inode < nodes.size(); ++inode ) tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(inode) ); - presentEditor->AddElement( tgtNodes, elemKind.Init( e )); + presentEditor->AddElement( tgtNodes, elemToCopy.Init( e )); } else // store present elements to add them to a group for ( int i = 0 ; i < presentBndElems.size(); ++i ) @@ -12738,7 +12798,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, tgtNodes.resize( elem->NbNodes() ); for ( inode = 0; inode < tgtNodes.size(); ++inode ) tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, elem->GetNode(inode) ); - tgtEditor.AddElement( tgtNodes, elemKind.Init( elem )); + tgtEditor.AddElement( tgtNodes, elemToCopy.Init( elem )); tgtEditor.myLastCreatedElems.Clear(); }