X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MeshEditor.cxx;h=76432855fe476d48e366cff1bc5fa5211dad0628;hb=91c92cb54310225231438b4d3bafeb0d1643a7c0;hp=f26db9a0cbe68c21c6d7f6ac02667a37449a2fc2;hpb=d8f644ca3d4ce62f2ef41d4aacb52f5bb1221df3;p=modules%2Fsmesh.git diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index f26db9a0c..76432855f 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -1,23 +1,23 @@ -// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE // -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. // -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // SMESH SMESH : idl implementation based on 'SMESH' unit's classes @@ -25,6 +25,7 @@ // Created : Mon Apr 12 16:10:22 2004 // Author : Edward AGAPOV (eap) // +#define CHRONODEF #include "SMESH_MeshEditor.hxx" #include "SMDS_FaceOfNodes.hxx" @@ -33,8 +34,10 @@ #include "SMDS_PolyhedralVolumeOfNodes.hxx" #include "SMDS_FacePosition.hxx" #include "SMDS_SpacePosition.hxx" -#include "SMDS_QuadraticFaceOfNodes.hxx" +//#include "SMDS_QuadraticFaceOfNodes.hxx" #include "SMDS_MeshGroup.hxx" +#include "SMDS_LinearEdge.hxx" +#include "SMDS_Downward.hxx" #include "SMDS_SetIterator.hxx" #include "SMESHDS_Group.hxx" @@ -91,6 +94,8 @@ #include #include #include +#include +#include #define cast2Node(elem) static_cast( elem ) @@ -124,103 +129,130 @@ SMESH_MeshEditor::AddElement(const vector & node, const bool isPoly, const int ID) { + //MESSAGE("AddElement " <Add0DElementWithID(node[0], ID); - else e = mesh->Add0DElement (node[0] ); - break; - case SMDSAbs_Edge: - if ( nbnode == 2 ) - if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], ID); - else e = mesh->AddEdge (node[0], node[1] ); - else if ( nbnode == 3 ) - if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID); - else e = mesh->AddEdge (node[0], node[1], node[2] ); - break; case SMDSAbs_Face: if ( !isPoly ) { - if (nbnode == 3) - if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], ID); - else e = mesh->AddFace (node[0], node[1], node[2] ); - else if (nbnode == 4) - if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], ID); - else e = mesh->AddFace (node[0], node[1], node[2], node[3] ); - else if (nbnode == 6) - if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], - node[4], node[5], ID); - else e = mesh->AddFace (node[0], node[1], node[2], node[3], - node[4], node[5] ); - else if (nbnode == 8) - if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], ID); - else e = mesh->AddFace (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7] ); + if (nbnode == 3) { + if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], ID); + else e = mesh->AddFace (node[0], node[1], node[2] ); + } + else if (nbnode == 4) { + if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], ID); + else e = mesh->AddFace (node[0], node[1], node[2], node[3] ); + } + else if (nbnode == 6) { + if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], + node[4], node[5], ID); + else e = mesh->AddFace (node[0], node[1], node[2], node[3], + node[4], node[5] ); + } + else if (nbnode == 8) { + if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], ID); + else e = mesh->AddFace (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7] ); + } } else { - if ( ID ) e = mesh->AddPolygonalFaceWithID(node, ID); - else e = mesh->AddPolygonalFace (node ); + if ( ID >= 1 ) e = mesh->AddPolygonalFaceWithID(node, ID); + else e = mesh->AddPolygonalFace (node ); } break; + case SMDSAbs_Volume: if ( !isPoly ) { - if (nbnode == 4) - if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3] ); - else if (nbnode == 5) - if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4] ); - else if (nbnode == 6) - if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5] ); - else if (nbnode == 8) - if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7] ); - else if (nbnode == 10) - if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], 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] ); - else if (nbnode == 13) - if ( ID ) 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],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] ); - else if (nbnode == 15) - if ( ID ) 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],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] ); - else if (nbnode == 20) - if ( ID ) 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],node[18],node[19],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],node[18],node[19] ); + if (nbnode == 4) { + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3] ); + } + else if (nbnode == 5) { + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4] ); + } + else if (nbnode == 6) { + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5] ); + } + else if (nbnode == 8) { + if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7] ); + } + else if (nbnode == 10) { + 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], 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] ); + } + else if (nbnode == 13) { + 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],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] ); + } + else if (nbnode == 15) { + 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],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] ); + } + 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], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14],node[15], + node[16],node[17],node[18],node[19],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],node[18],node[19] ); + } + } + break; + + case SMDSAbs_Edge: + if ( nbnode == 2 ) { + if ( ID >= 1 ) e = mesh->AddEdgeWithID(node[0], node[1], ID); + else e = mesh->AddEdge (node[0], node[1] ); + } + else if ( nbnode == 3 ) { + if ( ID >= 1 ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID); + else e = mesh->AddEdge (node[0], node[1], node[2] ); + } + break; + + case SMDSAbs_0DElement: + if ( nbnode == 1 ) { + if ( ID >= 1 ) e = mesh->Add0DElementWithID(node[0], ID); + else e = mesh->Add0DElement (node[0] ); } + break; + + case SMDSAbs_Node: + if ( ID >= 1 ) e = mesh->AddNodeWithID(node[0]->X(), node[0]->Y(), node[0]->Z(), ID); + else e = mesh->AddNode (node[0]->X(), node[0]->Y(), node[0]->Z()); + break; + + default:; } if ( e ) myLastCreatedElems.Append( e ); return e; @@ -279,7 +311,7 @@ int SMESH_MeshEditor::Remove (const list< int >& theIDs, if ( isNodes ) { const SMDS_MeshNode* node = cast2Node( elem ); if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX ) - if ( int aShapeID = node->GetPosition()->GetShapeId() ) + if ( int aShapeID = node->getshapeId() ) if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( aShapeID ) ) smmap.insert( sm ); } @@ -333,46 +365,55 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem) if ( aMesh->ShapeToMesh().IsNull() ) return 0; + int aShapeID = theElem->getshapeId(); + if ( aShapeID < 1 ) + return 0; + + if ( SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID )) + if ( sm->Contains( theElem )) + return aShapeID; + if ( theElem->GetType() == SMDSAbs_Node ) { - const SMDS_PositionPtr& aPosition = - static_cast( theElem )->GetPosition(); - if ( aPosition.get() ) - return aPosition->GetShapeId(); - else - return 0; + MESSAGE( ":( Error: invalid myShapeId of node " << theElem->GetID() ); + } + else { + MESSAGE( ":( Error: invalid myShapeId of element " << theElem->GetID() ); } - TopoDS_Shape aShape; // the shape a node is on - SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator(); - while ( nodeIt->more() ) { - const SMDS_MeshNode* node = static_cast( nodeIt->next() ); - const SMDS_PositionPtr& aPosition = node->GetPosition(); - if ( aPosition.get() ) { - int aShapeID = aPosition->GetShapeId(); - SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID ); - if ( sm ) { - if ( sm->Contains( theElem )) - return aShapeID; - if ( aShape.IsNull() ) - aShape = aMesh->IndexToShape( aShapeID ); - } - else { - //MESSAGE ( "::FindShape() No SubShape for aShapeID " << aShapeID ); + TopoDS_Shape aShape; // the shape a node of theElem is on + if ( theElem->GetType() != SMDSAbs_Node ) + { + SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator(); + while ( nodeIt->more() ) { + const SMDS_MeshNode* node = static_cast( nodeIt->next() ); + if ((aShapeID = node->getshapeId()) > 0) { + if ( SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID ) ) { + if ( sm->Contains( theElem )) + return aShapeID; + if ( aShape.IsNull() ) + aShape = aMesh->IndexToShape( aShapeID ); + } } } } // None of nodes is on a proper shape, // find the shape among ancestors of aShape on which a node is - if ( aShape.IsNull() ) { - //MESSAGE ("::FindShape() - NONE node is on shape") - return 0; + if ( !aShape.IsNull() ) { + TopTools_ListIteratorOfListOfShape ancIt( GetMesh()->GetAncestors( aShape )); + for ( ; ancIt.More(); ancIt.Next() ) { + SMESHDS_SubMesh * sm = aMesh->MeshElements( ancIt.Value() ); + if ( sm && sm->Contains( theElem )) + return aMesh->ShapeToIndex( ancIt.Value() ); + } } - TopTools_ListIteratorOfListOfShape ancIt( GetMesh()->GetAncestors( aShape )); - for ( ; ancIt.More(); ancIt.Next() ) { - SMESHDS_SubMesh * sm = aMesh->MeshElements( ancIt.Value() ); - if ( sm && sm->Contains( theElem )) - return aMesh->ShapeToIndex( ancIt.Value() ); + else + { + const map& id2sm = GetMeshDS()->SubMeshes(); + map::const_iterator id_sm = id2sm.begin(); + for ( ; id_sm != id2sm.end(); ++id_sm ) + if ( id_sm->second->Contains( theElem )) + return id_sm->first; } //MESSAGE ("::FindShape() - SHAPE NOT FOUND") @@ -479,15 +520,19 @@ static bool GetNodesFromTwoTria(const SMDS_MeshElement * theTria1, bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1, const SMDS_MeshElement * theTria2 ) { + MESSAGE("InverseDiag"); myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); if (!theTria1 || !theTria2) return false; - const SMDS_FaceOfNodes* F1 = dynamic_cast( theTria1 ); - const SMDS_FaceOfNodes* F2 = dynamic_cast( theTria2 ); - if (F1 && F2) { + const SMDS_VtkFace* F1 = dynamic_cast( theTria1 ); + if (!F1) return false; + const SMDS_VtkFace* F2 = dynamic_cast( theTria2 ); + if (!F2) return false; + if ((theTria1->GetEntityType() == SMDSEntity_Triangle) && + (theTria2->GetEntityType() == SMDSEntity_Triangle)) { // 1 +--+ A theTria1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A // | /| theTria2: ( B A 2 ) B->1 ( 1 A 2 ) |\ | @@ -524,12 +569,14 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1, // find indices of 1,2 and of A,B in theTria1 int iA = 0, iB = 0, i1 = 0, i2 = 0; for ( i = 0; i < 6; i++ ) { - if ( sameInd [ i ] == 0 ) + if ( sameInd [ i ] == 0 ) { if ( i < 3 ) i1 = i; else i2 = i; - else if (i < 3) + } + else if (i < 3) { if ( iA ) iB = i; else iA = i; + } } // nodes 1 and 2 should not be the same if ( aNodes[ i1 ] == aNodes[ i2 ] ) @@ -540,24 +587,18 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1, // theTria2: B->1 aNodes[ sameInd[ iB ]] = aNodes[ i1 ]; - //MESSAGE( theTria1 << theTria2 ); - GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 ); GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 ); - //MESSAGE( theTria1 << theTria2 ); - return true; } // end if(F1 && F2) // check case of quadratic faces - const SMDS_QuadraticFaceOfNodes* QF1 = - dynamic_cast (theTria1); - if(!QF1) return false; - const SMDS_QuadraticFaceOfNodes* QF2 = - dynamic_cast (theTria2); - if(!QF2) return false; + if (theTria1->GetEntityType() != SMDSEntity_Quad_Triangle) + return false; + if (theTria2->GetEntityType() != SMDSEntity_Quad_Triangle) + return false; // 5 // 1 +--+--+ 2 theTria1: (1 2 4 5 9 7) or (2 4 1 9 7 5) or (4 1 2 7 5 9) @@ -622,7 +663,7 @@ static bool findTriangles(const SMDS_MeshNode * theNode1, it = theNode2->GetInverseElementIterator(SMDSAbs_Face); while (it->more()) { const SMDS_MeshElement* elem = it->next(); - if ( emap.find( elem ) != emap.end() ) + if ( emap.find( elem ) != emap.end() ) { if ( theTria1 ) { // theTria1 must be element with minimum ID if( theTria1->GetID() < elem->GetID() ) { @@ -637,6 +678,7 @@ static bool findTriangles(const SMDS_MeshNode * theNode1, else { theTria1 = elem; } + } } return ( theTria1 && theTria2 ); } @@ -660,11 +702,12 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1, if ( !findTriangles( theNode1, theNode2, tr1, tr2 )) return false; - const SMDS_FaceOfNodes* F1 = dynamic_cast( tr1 ); - //if (!F1) return false; - const SMDS_FaceOfNodes* F2 = dynamic_cast( tr2 ); - //if (!F2) return false; - if (F1 && F2) { + const SMDS_VtkFace* F1 = dynamic_cast( tr1 ); + if (!F1) return false; + const SMDS_VtkFace* F2 = dynamic_cast( tr2 ); + if (!F2) return false; + if ((tr1->GetEntityType() == SMDSEntity_Triangle) && + (tr2->GetEntityType() == SMDSEntity_Triangle)) { // 1 +--+ A tr1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A // | /| tr2: ( B A 2 ) B->1 ( 1 A 2 ) |\ | @@ -702,23 +745,13 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1, // tr2: B->1 aNodes2[ iB2 ] = aNodes1[ i1 ]; - //MESSAGE( tr1 << tr2 ); - GetMeshDS()->ChangeElementNodes( tr1, aNodes1, 3 ); GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 ); - //MESSAGE( tr1 << tr2 ); - return true; } // check case of quadratic faces - const SMDS_QuadraticFaceOfNodes* QF1 = - dynamic_cast (tr1); - if(!QF1) return false; - const SMDS_QuadraticFaceOfNodes* QF2 = - dynamic_cast (tr2); - if(!QF2) return false; return InverseDiag(tr1,tr2); } @@ -792,34 +825,39 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, if ( !findTriangles( theNode1, theNode2, tr1, tr2 )) return false; - const SMDS_FaceOfNodes* F1 = dynamic_cast( tr1 ); - //if (!F1) return false; - const SMDS_FaceOfNodes* F2 = dynamic_cast( tr2 ); - //if (!F2) return false; - if (F1 && F2) { + const SMDS_VtkFace* F1 = dynamic_cast( tr1 ); + if (!F1) return false; + const SMDS_VtkFace* F2 = dynamic_cast( tr2 ); + if (!F2) return false; + SMESHDS_Mesh * aMesh = GetMeshDS(); + + if ((tr1->GetEntityType() == SMDSEntity_Triangle) && + (tr2->GetEntityType() == SMDSEntity_Triangle)) { const SMDS_MeshNode* aNodes [ 4 ]; if ( ! getQuadrangleNodes( aNodes, theNode1, theNode2, tr1, tr2 )) return false; - //MESSAGE( endl << tr1 << tr2 ); - - GetMeshDS()->ChangeElementNodes( tr1, aNodes, 4 ); - myLastCreatedElems.Append(tr1); - GetMeshDS()->RemoveElement( tr2 ); - - //MESSAGE( endl << tr1 ); + const SMDS_MeshElement* newElem = 0; + newElem = aMesh->AddFace( aNodes[0], aNodes[1], aNodes[2], aNodes[3] ); + myLastCreatedElems.Append(newElem); + AddToSameGroups( newElem, tr1, aMesh ); + int aShapeId = tr1->getshapeId(); + if ( aShapeId ) + { + aMesh->SetMeshElementOnShape( newElem, aShapeId ); + } + aMesh->RemoveElement( tr1 ); + aMesh->RemoveElement( tr2 ); return true; } // check case of quadratic faces - const SMDS_QuadraticFaceOfNodes* QF1 = - dynamic_cast (tr1); - if(!QF1) return false; - const SMDS_QuadraticFaceOfNodes* QF2 = - dynamic_cast (tr2); - if(!QF2) return false; + if (tr1->GetEntityType() != SMDSEntity_Quad_Triangle) + return false; + if (tr2->GetEntityType() != SMDSEntity_Quad_Triangle) + return false; // 5 // 1 +--+--+ 2 tr1: (1 2 4 5 9 7) or (2 4 1 9 7 5) or (4 1 2 7 5 9) @@ -849,9 +887,18 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, aNodes[6] = N2[3]; aNodes[7] = N1[5]; - GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 ); - myLastCreatedElems.Append(tr1); - GetMeshDS()->RemoveElement( tr2 ); + const SMDS_MeshElement* newElem = 0; + newElem = aMesh->AddFace( aNodes[0], aNodes[1], aNodes[2], aNodes[3], + aNodes[4], aNodes[5], aNodes[6], aNodes[7]); + myLastCreatedElems.Append(newElem); + AddToSameGroups( newElem, tr1, aMesh ); + int aShapeId = tr1->getshapeId(); + if ( aShapeId ) + { + aMesh->SetMeshElementOnShape( newElem, aShapeId ); + } + aMesh->RemoveElement( tr1 ); + aMesh->RemoveElement( tr2 ); // remove middle node (9) GetMeshDS()->RemoveNode( N1[4] ); @@ -866,6 +913,7 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem) { + MESSAGE("Reorient"); myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -912,8 +960,10 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem) } case SMDSAbs_Volume: { if (theElem->IsPoly()) { - const SMDS_PolyhedralVolumeOfNodes* aPolyedre = - static_cast( theElem ); + // TODO reorient vtk polyhedron + MESSAGE("reorient vtk polyhedron ?"); + const SMDS_VtkVolume* aPolyedre = + dynamic_cast( theElem ); if (!aPolyedre) { MESSAGE("Warning: bad volumic element"); return false; @@ -942,6 +992,7 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem) if ( !vTool.Set( theElem )) return false; vTool.Inverse(); + MESSAGE("ChangeElementNodes reorient: check vTool.Inverse"); return GetMeshDS()->ChangeElementNodes( theElem, vTool.GetNodes(), vTool.NbNodes() ); } } @@ -1014,21 +1065,21 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems, aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit ); int aShapeId = FindShape( elem ); - const SMDS_MeshElement* newElem = 0; + const SMDS_MeshElement* newElem1 = 0; + const SMDS_MeshElement* newElem2 = 0; if( !elem->IsQuadratic() ) { // split liner quadrangle - if ( aBadRate1 <= aBadRate2 ) { // tr1 + tr2 is better - aMesh->ChangeElementNodes( elem, aNodes, 3 ); - newElem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] ); + newElem1 = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] ); + newElem2 = aMesh->AddFace( aNodes[2], aNodes[0], aNodes[1] ); } else { // tr3 + tr4 is better - aMesh->ChangeElementNodes( elem, &aNodes[1], 3 ); - newElem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] ); + newElem1 = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] ); + newElem2 = aMesh->AddFace( aNodes[3], aNodes[1], aNodes[2] ); } } else { @@ -1081,39 +1132,34 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems, myLastCreatedNodes.Append(newN); // create a new element - const SMDS_MeshNode* N[6]; if ( aBadRate1 <= aBadRate2 ) { - N[0] = aNodes[0]; - N[1] = aNodes[1]; - N[2] = aNodes[2]; - N[3] = aNodes[4]; - N[4] = aNodes[5]; - N[5] = newN; - newElem = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0], - aNodes[6], aNodes[7], newN ); + newElem1 = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0], + aNodes[6], aNodes[7], newN ); + newElem2 = aMesh->AddFace(aNodes[2], aNodes[0], aNodes[1], + newN, aNodes[4], aNodes[5] ); } else { - N[0] = aNodes[1]; - N[1] = aNodes[2]; - N[2] = aNodes[3]; - N[3] = aNodes[5]; - N[4] = aNodes[6]; - N[5] = newN; - newElem = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1], - aNodes[7], aNodes[4], newN ); + newElem1 = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1], + aNodes[7], aNodes[4], newN ); + newElem2 = aMesh->AddFace(aNodes[3], aNodes[1], aNodes[2], + newN, aNodes[5], aNodes[6] ); } - aMesh->ChangeElementNodes( elem, N, 6 ); - } // quadratic case // care of a new element - myLastCreatedElems.Append(newElem); - AddToSameGroups( newElem, elem, aMesh ); + myLastCreatedElems.Append(newElem1); + myLastCreatedElems.Append(newElem2); + AddToSameGroups( newElem1, elem, aMesh ); + AddToSameGroups( newElem2, elem, aMesh ); // put a new triangle on the same shape if ( aShapeId ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); + { + aMesh->SetMeshElementOnShape( newElem1, aShapeId ); + aMesh->SetMeshElementOnShape( newElem2, aShapeId ); + } + aMesh->RemoveElement( elem ); } return true; } @@ -1516,14 +1562,14 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems, const int theMethodFlags) { // std-like iterator on coordinates of nodes of mesh element - typedef SMDS_StdIterator< TNodeXYZ, SMDS_ElemIteratorPtr > NXyzIterator; + typedef SMDS_StdIterator< SMESH_TNodeXYZ, SMDS_ElemIteratorPtr > NXyzIterator; NXyzIterator xyzEnd; SMDS_VolumeTool volTool; SMESH_MesherHelper helper( *GetMesh()); - SMESHDS_SubMesh* subMesh = GetMeshDS()->MeshElements(1); - SMESHDS_SubMesh* fSubMesh = subMesh; + SMESHDS_SubMesh* subMesh = 0;//GetMeshDS()->MeshElements(1); + SMESHDS_SubMesh* fSubMesh = 0;//subMesh; SMESH_SequenceOfElemPtr newNodes, newElems; @@ -1569,6 +1615,7 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems, helper.SetIsQuadratic( false ); } vector nodes( (*elem)->begin_nodes(), (*elem)->end_nodes() ); + helper.SetElementsOnShape( true ); if ( splitMethod._baryNode ) { // make a node at barycenter @@ -1596,7 +1643,6 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems, } // make tetras - helper.SetElementsOnShape( true ); vector tetras( splitMethod._nbTetra ); // splits of a volume const int* tetConn = splitMethod._connectivity; for ( int i = 0; i < splitMethod._nbTetra; ++i, tetConn += 4 ) @@ -1624,6 +1670,12 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems, helper.SetElementsOnShape( false ); vector< const SMDS_MeshElement* > triangles; + // find submesh to add new triangles in + if ( !fSubMesh || !fSubMesh->Contains( face )) + { + int shapeID = FindShape( face ); + fSubMesh = GetMeshDS()->MeshElements( shapeID ); + } map::iterator iF_n = splitMethod._faceBaryNode.find(iF); if ( iF_n != splitMethod._faceBaryNode.end() ) { @@ -1635,6 +1687,9 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems, if ( !volTool.IsFaceExternal( iF )) swap( n2, n3 ); triangles.push_back( helper.AddFace( n1,n2,n3 )); + + if ( fSubMesh && n3->getshapeId() < 1 ) + fSubMesh->AddNode( n3 ); } } else @@ -1673,18 +1728,12 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems, volNodes[ facet->_n3 ])); } } - // find submesh to add new triangles in - if ( !fSubMesh || !fSubMesh->Contains( face )) - { - int shapeID = FindShape( face ); - fSubMesh = GetMeshDS()->MeshElements( shapeID ); - } for ( int i = 0; i < triangles.size(); ++i ) { - if ( !triangles.back() ) continue; + if ( !triangles[i] ) continue; if ( fSubMesh ) - fSubMesh->AddElement( triangles.back()); - newElems.Append( triangles.back() ); + fSubMesh->AddElement( triangles[i]); + newElems.Append( triangles[i] ); } ReplaceElemInGroups( face, triangles, GetMeshDS() ); GetMeshDS()->RemoveFreeElement( face, fSubMesh, /*fromGroups=*/false ); @@ -1821,20 +1870,28 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems, aNodes[ i++ ] = static_cast( itN->next() ); int aShapeId = FindShape( elem ); - const SMDS_MeshElement* newElem = 0; + const SMDS_MeshElement* newElem1 = 0; + const SMDS_MeshElement* newElem2 = 0; if ( the13Diag ) { - aMesh->ChangeElementNodes( elem, aNodes, 3 ); - newElem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] ); + newElem1 = aMesh->AddFace( aNodes[2], aNodes[0], aNodes[1] ); + newElem2 = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] ); } else { - aMesh->ChangeElementNodes( elem, &aNodes[1], 3 ); - newElem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] ); + newElem1 = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] ); + newElem2 = aMesh->AddFace( aNodes[3], aNodes[1], aNodes[2] ); } - myLastCreatedElems.Append(newElem); + myLastCreatedElems.Append(newElem1); + myLastCreatedElems.Append(newElem2); // put a new triangle on the same shape and add to the same groups if ( aShapeId ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); - AddToSameGroups( newElem, elem, aMesh ); + { + aMesh->SetMeshElementOnShape( newElem1, aShapeId ); + aMesh->SetMeshElementOnShape( newElem2, aShapeId ); + } + AddToSameGroups( newElem1, elem, aMesh ); + AddToSameGroups( newElem2, elem, aMesh ); + //aMesh->RemoveFreeElement(elem, aMesh->MeshElements(aShapeId), true); + aMesh->RemoveElement( elem ); } // Quadratic quadrangle @@ -1889,34 +1946,31 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems, myLastCreatedNodes.Append(newN); // create a new element - const SMDS_MeshElement* newElem = 0; - const SMDS_MeshNode* N[6]; + const SMDS_MeshElement* newElem1 = 0; + const SMDS_MeshElement* newElem2 = 0; if ( the13Diag ) { - N[0] = aNodes[0]; - N[1] = aNodes[1]; - N[2] = aNodes[2]; - N[3] = aNodes[4]; - N[4] = aNodes[5]; - N[5] = newN; - newElem = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0], - aNodes[6], aNodes[7], newN ); + newElem1 = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0], + aNodes[6], aNodes[7], newN ); + newElem2 = aMesh->AddFace(aNodes[2], aNodes[0], aNodes[1], + newN, aNodes[4], aNodes[5] ); } else { - N[0] = aNodes[1]; - N[1] = aNodes[2]; - N[2] = aNodes[3]; - N[3] = aNodes[5]; - N[4] = aNodes[6]; - N[5] = newN; - newElem = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1], - aNodes[7], aNodes[4], newN ); + newElem1 = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1], + aNodes[7], aNodes[4], newN ); + newElem2 = aMesh->AddFace(aNodes[3], aNodes[1], aNodes[2], + newN, aNodes[5], aNodes[6] ); } - myLastCreatedElems.Append(newElem); - aMesh->ChangeElementNodes( elem, N, 6 ); + myLastCreatedElems.Append(newElem1); + myLastCreatedElems.Append(newElem2); // put a new triangle on the same shape and add to the same groups if ( aShapeId ) - aMesh->SetMeshElementOnShape( newElem, aShapeId ); - AddToSameGroups( newElem, elem, aMesh ); + { + aMesh->SetMeshElementOnShape( newElem1, aShapeId ); + aMesh->SetMeshElementOnShape( newElem2, aShapeId ); + } + AddToSameGroups( newElem1, elem, aMesh ); + AddToSameGroups( newElem2, elem, aMesh ); + aMesh->RemoveElement( elem ); } } @@ -1962,7 +2016,7 @@ double getAngle(const SMDS_MeshElement * tr1, int i = 0, iDiag = -1; while ( it->more()) { const SMDS_MeshElement *n = it->next(); - if ( n == n1 || n == n2 ) + if ( n == n1 || n == n2 ) { if ( iDiag < 0) iDiag = i; else { @@ -1972,6 +2026,7 @@ double getAngle(const SMDS_MeshElement * tr1, nFirst[ t ] = n; break; } + } i++; } } @@ -2212,16 +2267,17 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems, mapEl_setLi.erase( tr2 ); mapLi_listEl.erase( *link12 ); if(tr1->NbNodes()==3) { - if( tr1->GetID() < tr2->GetID() ) { - aMesh->ChangeElementNodes( tr1, n12, 4 ); - myLastCreatedElems.Append(tr1); - aMesh->RemoveElement( tr2 ); - } - else { - aMesh->ChangeElementNodes( tr2, n12, 4 ); - myLastCreatedElems.Append(tr2); - aMesh->RemoveElement( tr1); - } + const SMDS_MeshElement* newElem = 0; + newElem = aMesh->AddFace(n12[0], n12[1], n12[2], n12[3] ); + myLastCreatedElems.Append(newElem); + AddToSameGroups( newElem, tr1, aMesh ); + int aShapeId = tr1->getshapeId(); + if ( aShapeId ) + { + aMesh->SetMeshElementOnShape( newElem, aShapeId ); + } + aMesh->RemoveElement( tr1 ); + aMesh->RemoveElement( tr2 ); } else { const SMDS_MeshNode* N1 [6]; @@ -2239,16 +2295,18 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems, aNodes[5] = N2[5]; aNodes[6] = N2[3]; aNodes[7] = N1[5]; - if( tr1->GetID() < tr2->GetID() ) { - GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 ); - myLastCreatedElems.Append(tr1); - GetMeshDS()->RemoveElement( tr2 ); - } - else { - GetMeshDS()->ChangeElementNodes( tr2, aNodes, 8 ); - myLastCreatedElems.Append(tr2); - GetMeshDS()->RemoveElement( tr1 ); - } + const SMDS_MeshElement* newElem = 0; + newElem = aMesh->AddFace(aNodes[0], aNodes[1], aNodes[2], aNodes[3], + aNodes[4], aNodes[5], aNodes[6], aNodes[7]); + myLastCreatedElems.Append(newElem); + AddToSameGroups( newElem, tr1, aMesh ); + int aShapeId = tr1->getshapeId(); + if ( aShapeId ) + { + aMesh->SetMeshElementOnShape( newElem, aShapeId ); + } + aMesh->RemoveElement( tr1 ); + aMesh->RemoveElement( tr2 ); // remove middle node (9) GetMeshDS()->RemoveNode( N1[4] ); } @@ -2257,16 +2315,17 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems, mapEl_setLi.erase( tr3 ); mapLi_listEl.erase( *link13 ); if(tr1->NbNodes()==3) { - if( tr1->GetID() < tr2->GetID() ) { - aMesh->ChangeElementNodes( tr1, n13, 4 ); - myLastCreatedElems.Append(tr1); - aMesh->RemoveElement( tr3 ); - } - else { - aMesh->ChangeElementNodes( tr3, n13, 4 ); - myLastCreatedElems.Append(tr3); - aMesh->RemoveElement( tr1 ); - } + const SMDS_MeshElement* newElem = 0; + newElem = aMesh->AddFace(n13[0], n13[1], n13[2], n13[3] ); + myLastCreatedElems.Append(newElem); + AddToSameGroups( newElem, tr1, aMesh ); + int aShapeId = tr1->getshapeId(); + if ( aShapeId ) + { + aMesh->SetMeshElementOnShape( newElem, aShapeId ); + } + aMesh->RemoveElement( tr1 ); + aMesh->RemoveElement( tr3 ); } else { const SMDS_MeshNode* N1 [6]; @@ -2284,16 +2343,18 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems, aNodes[5] = N2[5]; aNodes[6] = N2[3]; aNodes[7] = N1[5]; - if( tr1->GetID() < tr2->GetID() ) { - GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 ); - myLastCreatedElems.Append(tr1); - GetMeshDS()->RemoveElement( tr3 ); - } - else { - GetMeshDS()->ChangeElementNodes( tr3, aNodes, 8 ); - myLastCreatedElems.Append(tr3); - GetMeshDS()->RemoveElement( tr1 ); - } + const SMDS_MeshElement* newElem = 0; + newElem = aMesh->AddFace(aNodes[0], aNodes[1], aNodes[2], aNodes[3], + aNodes[4], aNodes[5], aNodes[6], aNodes[7]); + myLastCreatedElems.Append(newElem); + AddToSameGroups( newElem, tr1, aMesh ); + int aShapeId = tr1->getshapeId(); + if ( aShapeId ) + { + aMesh->SetMeshElementOnShape( newElem, aShapeId ); + } + aMesh->RemoveElement( tr1 ); + aMesh->RemoveElement( tr3 ); // remove middle node (9) GetMeshDS()->RemoveNode( N1[4] ); } @@ -2609,6 +2670,9 @@ void SMESH_MeshEditor::GetLinkedNodes( const SMDS_MeshNode* theNode, while ( elemIt->more() ) { const SMDS_MeshElement* elem = elemIt->next(); + if(elem->GetType() == SMDSAbs_0DElement) + continue; + SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); if ( elem->GetType() == SMDSAbs_Volume ) { @@ -2841,7 +2905,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, Handle(Geom_Surface) surface; SMESHDS_SubMesh* faceSubMesh = 0; TopoDS_Face face; - double fToler2 = 0, vPeriod = 0., uPeriod = 0., f,l; + double fToler2 = 0, f,l; double u1 = 0, u2 = 0, v1 = 0, v2 = 0; bool isUPeriodic = false, isVPeriodic = false; if ( *fId ) { @@ -2852,10 +2916,10 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, fToler2 *= fToler2 * 10.; isUPeriodic = surface->IsUPeriodic(); if ( isUPeriodic ) - vPeriod = surface->UPeriod(); + surface->UPeriod(); isVPeriodic = surface->IsVPeriodic(); if ( isVPeriodic ) - uPeriod = surface->VPeriod(); + surface->VPeriod(); surface->Bounds( u1, u2, v1, v2 ); } // --------------------------------------------------------- @@ -2905,7 +2969,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, while ( nn++ < nbn ) { node = static_cast( itN->next() ); const SMDS_PositionPtr& pos = node->GetPosition(); - posType = pos.get() ? pos->GetTypeOfPosition() : SMDS_TOP_3DSPACE; + posType = pos ? pos->GetTypeOfPosition() : SMDS_TOP_3DSPACE; if (posType != SMDS_TOP_EDGE && posType != SMDS_TOP_VERTEX && theFixedNodes.find( node ) == theFixedNodes.end()) @@ -2963,27 +3027,27 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, node = *n; gp_XY uv( 0, 0 ); const SMDS_PositionPtr& pos = node->GetPosition(); - posType = pos.get() ? pos->GetTypeOfPosition() : SMDS_TOP_3DSPACE; + posType = pos ? pos->GetTypeOfPosition() : SMDS_TOP_3DSPACE; // get existing UV switch ( posType ) { case SMDS_TOP_FACE: { - SMDS_FacePosition* fPos = ( SMDS_FacePosition* ) pos.get(); + SMDS_FacePosition* fPos = ( SMDS_FacePosition* ) pos; uv.SetCoord( fPos->GetUParameter(), fPos->GetVParameter() ); break; } case SMDS_TOP_EDGE: { - TopoDS_Shape S = aMesh->IndexToShape( pos->GetShapeId() ); + TopoDS_Shape S = aMesh->IndexToShape( node->getshapeId() ); Handle(Geom2d_Curve) pcurve; if ( !S.IsNull() && S.ShapeType() == TopAbs_EDGE ) pcurve = BRep_Tool::CurveOnSurface( TopoDS::Edge( S ), face, f,l ); if ( !pcurve.IsNull() ) { - double u = (( SMDS_EdgePosition* ) pos.get() )->GetUParameter(); + double u = (( SMDS_EdgePosition* ) pos )->GetUParameter(); uv = pcurve->Value( u ).XY(); } break; } case SMDS_TOP_VERTEX: { - TopoDS_Shape S = aMesh->IndexToShape( pos->GetShapeId() ); + TopoDS_Shape S = aMesh->IndexToShape( node->getshapeId() ); if ( !S.IsNull() && S.ShapeType() == TopAbs_VERTEX ) uv = BRep_Tool::Parameters( TopoDS::Vertex( S ), face ).XY(); break; @@ -3027,35 +3091,27 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, // fix nodes on mesh boundary if ( checkBoundaryNodes ) { - map< NLink, int > linkNbMap; // how many times a link encounters in elemsOnFace - map< NLink, int >::iterator link_nb; + map< SMESH_TLink, int > linkNbMap; // how many times a link encounters in elemsOnFace + map< SMESH_TLink, int >::iterator link_nb; // put all elements links to linkNbMap list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin(); for ( ; elemIt != elemsOnFace.end(); ++elemIt ) { const SMDS_MeshElement* elem = (*elemIt); - int nbn = elem->NbNodes(); - if(elem->IsQuadratic()) - nbn = nbn/2; + int nbn = elem->NbCornerNodes(); // loop on elem links: insert them in linkNbMap - const SMDS_MeshNode* curNode, *prevNode = elem->GetNodeWrap( nbn ); for ( int iN = 0; iN < nbn; ++iN ) { - curNode = elem->GetNode( iN ); - NLink link; - if ( curNode < prevNode ) link = make_pair( curNode , prevNode ); - else link = make_pair( prevNode , curNode ); - prevNode = curNode; - link_nb = linkNbMap.find( link ); - if ( link_nb == linkNbMap.end() ) - linkNbMap.insert( make_pair ( link, 1 )); - else - link_nb->second++; + const SMDS_MeshNode* n1 = elem->GetNode( iN ); + const SMDS_MeshNode* n2 = elem->GetNode(( iN+1 ) % nbn); + SMESH_TLink link( n1, n2 ); + link_nb = linkNbMap.insert( make_pair( link, 0 )).first; + link_nb->second++; } } // remove nodes that are in links encountered only once from setMovableNodes for ( link_nb = linkNbMap.begin(); link_nb != linkNbMap.end(); ++link_nb ) { if ( link_nb->second == 1 ) { - setMovableNodes.erase( link_nb->first.first ); - setMovableNodes.erase( link_nb->first.second ); + setMovableNodes.erase( link_nb->first.node1() ); + setMovableNodes.erase( link_nb->first.node2() ); } } } @@ -3246,7 +3302,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, if ( node_uv != uvMap.end() ) { gp_XY* uv = node_uv->second; node->SetPosition - ( SMDS_PositionPtr( new SMDS_FacePosition( *fId, uv->X(), uv->Y() ))); + ( SMDS_PositionPtr( new SMDS_FacePosition( uv->X(), uv->Y() ))); } } @@ -3258,14 +3314,14 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, helper.SetSubShape( face ); list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin(); for ( ; elemIt != elemsOnFace.end(); ++elemIt ) { - const SMDS_QuadraticFaceOfNodes* QF = - dynamic_cast (*elemIt); - if(QF) { + const SMDS_VtkFace* QF = + dynamic_cast (*elemIt); + if(QF && QF->IsQuadratic()) { vector Ns; Ns.reserve(QF->NbNodes()+1); - SMDS_NodeIteratorPtr anIter = QF->interlacedNodesIterator(); + SMDS_ElemIteratorPtr anIter = QF->interlacedNodesElemIterator(); while ( anIter->more() ) - Ns.push_back( anIter->next() ); + Ns.push_back( cast2Node(anIter->next()) ); Ns.push_back( Ns[0] ); double x, y, z; for(int i=0; iNbNodes(); i=i+2) { @@ -3343,6 +3399,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, const int nbSteps, SMESH_SequenceOfElemPtr& srcElements) { + //MESSAGE("sweepElement " << nbSteps); SMESHDS_Mesh* aMesh = GetMeshDS(); // Loop on elem nodes: @@ -3381,7 +3438,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, } } - //cout<<" nbSame = "<GetID() ); //INFOS( " Too many same nodes of element " << elem->GetID() ); @@ -3418,6 +3475,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, } // make new elements + const SMDS_MeshElement* lastElem = elem; for (int iStep = 0; iStep < nbSteps; iStep++ ) { // get next nodes for ( iNode = 0; iNode < nbNodes; iNode++ ) { @@ -3433,7 +3491,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, nextNod[ iNode ] = *itNN[ iNode ]; itNN[ iNode ]++; } - else if(!elem->IsQuadratic() || elem->IsMediumNode(prevNod[iNode]) ) { + else if(!elem->IsQuadratic() || lastElem->IsMediumNode(prevNod[iNode]) ) { // we have to use each second node //itNN[ iNode ]++; nextNod[ iNode ] = *itNN[ iNode ]; @@ -3738,6 +3796,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, newElems.push_back( aNewElem ); myLastCreatedElems.Append(aNewElem); srcElements.Append( elem ); + lastElem = aNewElem; } // set new prev nodes @@ -3766,6 +3825,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, const int nbSteps, SMESH_SequenceOfElemPtr& srcElements) { + MESSAGE("makeWalls"); ASSERT( newElemsMap.size() == elemNewNodesMap.size() ); SMESHDS_Mesh* aMesh = GetMeshDS(); @@ -3809,6 +3869,8 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, const SMDS_MeshElement* elem = itElem->first; vector& vecNewNodes = itElemNodes->second; + if(itElem->second.size()==0) continue; + if ( elem->GetType() == SMDSAbs_Edge ) { // create a ceiling edge if (!elem->IsQuadratic()) { @@ -3833,8 +3895,6 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, if ( elem->GetType() != SMDSAbs_Face ) continue; - if(itElem->second.size()==0) continue; - bool hasFreeLinks = false; TIDSortedElemSet avoidSet; @@ -3954,79 +4014,111 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, for ( int iStep = 0; iStep < nbSteps; iStep++ ) { vTool.Set( *v ); vTool.SetExternalNormal(); + const int nextShift = vTool.IsForward() ? +1 : -1; list< int >::iterator ind = freeInd.begin(); list< const SMDS_MeshElement* >::iterator srcEdge = srcEdges.begin(); for ( ; ind != freeInd.end(); ++ind, ++srcEdge ) // loop on free faces { const SMDS_MeshNode** nodes = vTool.GetFaceNodes( *ind ); int nbn = vTool.NbFaceNodes( *ind ); - switch ( nbn ) { - case 3: { ///// triangle - const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]); - if ( !f ) - myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] )); - else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) - aMesh->ChangeElementNodes( f, nodes, nbn ); - break; - } - case 4: { ///// quadrangle - const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]); - if ( !f ) - myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] )); - else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) - aMesh->ChangeElementNodes( f, nodes, nbn ); - break; - } - default: - if( (*v)->IsQuadratic() ) { - if(nbn==6) { /////// quadratic triangle - const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], - nodes[1], nodes[3], nodes[5] ); - if ( !f ) { - myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], - nodes[1], nodes[3], nodes[5])); - } - else if ( nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) { - const SMDS_MeshNode** tmpnodes = new const SMDS_MeshNode*[6]; - tmpnodes[0] = nodes[0]; - tmpnodes[1] = nodes[2]; - tmpnodes[2] = nodes[4]; - tmpnodes[3] = nodes[1]; - tmpnodes[4] = nodes[3]; - tmpnodes[5] = nodes[5]; - aMesh->ChangeElementNodes( f, tmpnodes, nbn ); - } + if ( ! (*v)->IsPoly() ) + switch ( nbn ) { + case 3: { ///// triangle + const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]); + if ( !f || + nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ]) + nextShift )) + { + const SMDS_MeshNode* newOrder[3] = { nodes[ 1 - nextShift ], + nodes[ 1 ], + nodes[ 1 + nextShift ] }; + if ( f ) + aMesh->ChangeElementNodes( f, &newOrder[0], nbn ); + else + myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ], + newOrder[ 2 ] )); } - else { /////// quadratic quadrangle - const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[6], - nodes[1], nodes[3], nodes[5], nodes[7] ); - if ( !f ) { - myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6], - nodes[1], nodes[3], nodes[5], nodes[7])); - } - else if ( nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) { - const SMDS_MeshNode** tmpnodes = new const SMDS_MeshNode*[8]; - tmpnodes[0] = nodes[0]; - tmpnodes[1] = nodes[2]; - tmpnodes[2] = nodes[4]; - tmpnodes[3] = nodes[6]; - tmpnodes[4] = nodes[1]; - tmpnodes[5] = nodes[3]; - tmpnodes[6] = nodes[5]; - tmpnodes[7] = nodes[7]; - aMesh->ChangeElementNodes( f, tmpnodes, nbn ); - } + break; + } + case 4: { ///// quadrangle + const SMDS_MeshFace * f = + aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]); + if ( !f || + nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ]) + nextShift )) + { + const SMDS_MeshNode* newOrder[4] = { nodes[ 0 ], nodes[ 2-nextShift ], + nodes[ 2 ], nodes[ 2+nextShift ] }; + if ( f ) + aMesh->ChangeElementNodes( f, &newOrder[0], nbn ); + else + myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ], + newOrder[ 2 ], newOrder[ 3 ])); + } + break; + } + case 6: { /////// quadratic triangle + const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], + nodes[1], nodes[3], nodes[5] ); + if ( !f || + nodes[2] != f->GetNodeWrap( f->GetNodeIndex( nodes[0] ) + 2*nextShift )) + { + const SMDS_MeshNode* newOrder[6] = { nodes[2 - 2*nextShift], + nodes[2], + nodes[2 + 2*nextShift], + nodes[3 - 2*nextShift], + nodes[3], + nodes[3 + 2*nextShift]}; + if ( f ) + aMesh->ChangeElementNodes( f, &newOrder[0], nbn ); + else + myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], + newOrder[ 1 ], + newOrder[ 2 ], + newOrder[ 3 ], + newOrder[ 4 ], + newOrder[ 5 ] )); } + break; } - else { //////// polygon - vector polygon_nodes ( nodes, &nodes[nbn] ); - const SMDS_MeshFace * f = aMesh->FindFace( polygon_nodes ); - if ( !f ) - myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes)); - else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) - aMesh->ChangeElementNodes( f, nodes, nbn ); + default: /////// quadratic quadrangle + const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[6], + nodes[1], nodes[3], nodes[5], nodes[7] ); + if ( !f || + nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 2*nextShift )) + { + const SMDS_MeshNode* newOrder[8] = { nodes[0], + nodes[4 - 2*nextShift], + nodes[4], + nodes[4 + 2*nextShift], + nodes[1], + nodes[5 - 2*nextShift], + nodes[5], + nodes[5 + 2*nextShift] }; + if ( f ) + aMesh->ChangeElementNodes( f, &newOrder[0], nbn ); + else + myLastCreatedElems.Append(aMesh->AddFace(newOrder[ 0 ], newOrder[ 1 ], + newOrder[ 2 ], newOrder[ 3 ], + newOrder[ 4 ], newOrder[ 5 ], + newOrder[ 6 ], newOrder[ 7 ])); + } + } // switch ( nbn ) + + else { //////// polygon + + vector polygon_nodes ( nodes, &nodes[nbn] ); + const SMDS_MeshFace * f = aMesh->FindFace( polygon_nodes ); + if ( !f || + nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + nextShift )) + { + if ( !vTool.IsForward() ) + std::reverse( polygon_nodes.begin(), polygon_nodes.end()); + if ( f ) + aMesh->ChangeElementNodes( f, &polygon_nodes[0], nbn ); + else + AddElement(polygon_nodes, SMDSAbs_Face, polygon_nodes.size()>4); } } + while ( srcElements.Length() < myLastCreatedElems.Length() ) srcElements.Append( *srcEdge ); @@ -4035,8 +4127,9 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, // go to the next volume iVol = 0; while ( iVol++ < nbVolumesByStep ) v++; - } - } + + } // loop on steps + } // loop on volumes of one step } // sweep free links into faces // Make a ceiling face with a normal external to a volume @@ -4322,6 +4415,7 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems, const int theFlags, const double theTolerance) { + MESSAGE("ExtrusionSweep " << theMakeGroups << " " << theFlags << " " << theTolerance); myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -4522,6 +4616,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, const gp_Pnt& theRefPoint, const bool theMakeGroups) { + MESSAGE("ExtrusionAlongTrack"); myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -4580,7 +4675,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, while ( aItN->more() ) { const SMDS_MeshNode* pNode = aItN->next(); const SMDS_EdgePosition* pEPos = - static_cast( pNode->GetPosition().get() ); + static_cast( pNode->GetPosition() ); double aT = pEPos->GetUParameter(); aPrms.push_back( aT ); } @@ -4624,7 +4719,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, while ( aItN->more() ) { const SMDS_MeshNode* pNode = aItN->next(); const SMDS_EdgePosition* pEPos = - static_cast( pNode->GetPosition().get() ); + static_cast( pNode->GetPosition() ); double aT = pEPos->GetUParameter(); aPrms.push_back( aT ); } @@ -4752,7 +4847,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, const SMDS_MeshNode* pNode = aItN->next(); if( pNode==aN1 || pNode==aN2 ) continue; const SMDS_EdgePosition* pEPos = - static_cast( pNode->GetPosition().get() ); + static_cast( pNode->GetPosition() ); double aT = pEPos->GetUParameter(); aPrms.push_back( aT ); } @@ -4799,7 +4894,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, while ( aItN->more() ) { const SMDS_MeshNode* pNode = aItN->next(); const SMDS_EdgePosition* pEPos = - static_cast( pNode->GetPosition().get() ); + static_cast( pNode->GetPosition() ); double aT = pEPos->GetUParameter(); aPrms.push_back( aT ); } @@ -4827,9 +4922,6 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, list currList = *itLLPP; itPP = currList.begin(); SMESH_MeshEditor_PathPoint PP2 = currList.front(); - gp_Pnt P1 = PP1.Pnt(); - //cout<<" PP1: Pnt("<IsQuadratic " << elem->IsQuadratic() << " " << elem->IsMediumNode(node)); if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) { // create additional node double x = ( aPN1.X() + aPN0.X() )/2.; @@ -5209,7 +5303,7 @@ void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps, * \param theCopy - if true, create translated copies of theElems * \param theMakeGroups - if true and theCopy, create translated groups * \param theTargetMesh - mesh to copy translated elements into - * \retval SMESH_MeshEditor::PGroupIDs - list of ids of created groups + * \return SMESH_MeshEditor::PGroupIDs - list of ids of created groups */ //================================================================================ @@ -5227,22 +5321,37 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, string groupPostfix; switch ( theTrsf.Form() ) { case gp_PntMirror: + MESSAGE("gp_PntMirror"); + needReverse = true; + groupPostfix = "mirrored"; + break; case gp_Ax1Mirror: + MESSAGE("gp_Ax1Mirror"); + groupPostfix = "mirrored"; + break; case gp_Ax2Mirror: + MESSAGE("gp_Ax2Mirror"); needReverse = true; groupPostfix = "mirrored"; break; case gp_Rotation: + MESSAGE("gp_Rotation"); groupPostfix = "rotated"; break; case gp_Translation: + MESSAGE("gp_Translation"); groupPostfix = "translated"; break; case gp_Scale: + MESSAGE("gp_Scale"); + groupPostfix = "scaled"; + break; case gp_CompoundTrsf: // different scale by axis + MESSAGE("gp_CompoundTrsf"); groupPostfix = "scaled"; break; default: + MESSAGE("default"); needReverse = false; groupPostfix = "transformed"; } @@ -5263,8 +5372,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, SMESH_SequenceOfElemPtr srcElems, srcNodes; // issue 021015: EDF 1578 SMESH: Free nodes are removed when translating a mesh - list orphanCopy; // copies of orphan nodes - vector orphanNode; // original orphan nodes + TIDSortedElemSet orphanNode; if ( theElems.empty() ) // transform the whole mesh { @@ -5272,28 +5380,20 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, SMDS_ElemIteratorPtr eIt = aMesh->elementsIterator(); while ( eIt->more() ) theElems.insert( eIt->next() ); // add orphan nodes - SMDS_MeshElementIDFactory idFactory; SMDS_NodeIteratorPtr nIt = aMesh->nodesIterator(); while ( nIt->more() ) { const SMDS_MeshNode* node = nIt->next(); - if ( node->NbInverseElements() == 0 && !theElems.insert( node ).second ) - { - // node was not inserted into theElems because an element with the same ID - // is already there. As a work around we insert a copy of node with - // an ID = - - orphanCopy.push_back( *node ); // copy node - SMDS_MeshNode* nodeCopy = &orphanCopy.back(); - int uniqueID = -orphanNode.size(); - orphanNode.push_back( node ); - idFactory.BindID( uniqueID, nodeCopy ); - theElems.insert( nodeCopy ); - } + if ( node->NbInverseElements() == 0) + orphanNode.insert( node ); } } - // loop on theElems to transorm nodes + + // loop on elements to transform nodes : first orphan nodes then elems TIDSortedElemSet::iterator itElem; - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { + TIDSortedElemSet *elements[] = {&orphanNode, &theElems }; + for (int i=0; i<2; i++) + for ( itElem = elements[i]->begin(); itElem != elements[i]->end(); itElem++ ) { const SMDS_MeshElement* elem = *itElem; if ( !elem ) continue; @@ -5303,8 +5403,6 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, while ( itN->more() ) { const SMDS_MeshNode* node = cast2Node( itN->next() ); - if ( node->GetID() < 0 ) - node = orphanNode[ -node->GetID() ]; // check if a node has been already transformed pair n2n_isnew = nodeMap.insert( make_pair ( node, node )); @@ -5355,7 +5453,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, theElems.insert( *invElemIt ); // replicate or reverse elements - + // TODO revoir ordre reverse vtk enum { REV_TETRA = 0, // = nbNodes - 4 REV_PYRAMID = 1, // = nbNodes - 4 @@ -5423,8 +5521,8 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, case SMDSAbs_Volume: { // ATTENTION: Reversing is not yet done!!! - const SMDS_PolyhedralVolumeOfNodes* aPolyedre = - dynamic_cast( elem ); + const SMDS_VtkVolume* aPolyedre = + dynamic_cast( elem ); if (!aPolyedre) { MESSAGE("Warning: bad volumic element"); continue; @@ -5471,12 +5569,12 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, // Regular elements int* i = index[ FORWARD ]; - if ( needReverse && nbNodes > 2) // reverse mirrored faces and volumes + if ( needReverse && nbNodes > 2) {// reverse mirrored faces and volumes if ( elemType == SMDSAbs_Face ) i = index[ REV_FACE ]; else i = index[ nbNodes - 4 ]; - + } if(elem->IsQuadratic()) { static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; i = anIds; @@ -5547,13 +5645,339 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, PGroupIDs newGroupIDs; - if ( theMakeGroups && theCopy || - theMakeGroups && theTargetMesh ) + if ( ( theMakeGroups && theCopy ) || + ( theMakeGroups && theTargetMesh ) ) newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh ); return newGroupIDs; } + +////======================================================================= +////function : Scale +////purpose : +////======================================================================= +// +//SMESH_MeshEditor::PGroupIDs +//SMESH_MeshEditor::Scale (TIDSortedElemSet & theElems, +// const gp_Pnt& thePoint, +// const std::list& theScaleFact, +// const bool theCopy, +// const bool theMakeGroups, +// SMESH_Mesh* theTargetMesh) +//{ +// MESSAGE("Scale"); +// myLastCreatedElems.Clear(); +// myLastCreatedNodes.Clear(); +// +// SMESH_MeshEditor targetMeshEditor( theTargetMesh ); +// SMESHDS_Mesh* aTgtMesh = theTargetMesh ? theTargetMesh->GetMeshDS() : 0; +// SMESHDS_Mesh* aMesh = GetMeshDS(); +// +// double scaleX=1.0, scaleY=1.0, scaleZ=1.0; +// std::list::const_iterator itS = theScaleFact.begin(); +// scaleX = (*itS); +// if(theScaleFact.size()==1) { +// scaleY = (*itS); +// scaleZ= (*itS); +// } +// if(theScaleFact.size()==2) { +// itS++; +// scaleY = (*itS); +// scaleZ= (*itS); +// } +// if(theScaleFact.size()>2) { +// itS++; +// scaleY = (*itS); +// itS++; +// scaleZ= (*itS); +// } +// +// // map old node to new one +// TNodeNodeMap nodeMap; +// +// // elements sharing moved nodes; those of them which have all +// // nodes mirrored but are not in theElems are to be reversed +// TIDSortedElemSet inverseElemSet; +// +// // source elements for each generated one +// SMESH_SequenceOfElemPtr srcElems, srcNodes; +// +// // loop on theElems +// TIDSortedElemSet::iterator itElem; +// for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { +// const SMDS_MeshElement* elem = *itElem; +// if ( !elem ) +// continue; +// +// // loop on elem nodes +// SMDS_ElemIteratorPtr itN = elem->nodesIterator(); +// while ( itN->more() ) { +// +// // check if a node has been already transformed +// const SMDS_MeshNode* node = cast2Node( itN->next() ); +// pair n2n_isnew = +// nodeMap.insert( make_pair ( node, node )); +// if ( !n2n_isnew.second ) +// continue; +// +// //double coord[3]; +// //coord[0] = node->X(); +// //coord[1] = node->Y(); +// //coord[2] = node->Z(); +// //theTrsf.Transforms( coord[0], coord[1], coord[2] ); +// double dx = (node->X() - thePoint.X()) * scaleX; +// double dy = (node->Y() - thePoint.Y()) * scaleY; +// double dz = (node->Z() - thePoint.Z()) * scaleZ; +// if ( theTargetMesh ) { +// //const SMDS_MeshNode * newNode = aTgtMesh->AddNode( coord[0], coord[1], coord[2] ); +// const SMDS_MeshNode * newNode = +// aTgtMesh->AddNode( thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz ); +// n2n_isnew.first->second = newNode; +// myLastCreatedNodes.Append(newNode); +// srcNodes.Append( node ); +// } +// else if ( theCopy ) { +// //const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); +// const SMDS_MeshNode * newNode = +// aMesh->AddNode( thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz ); +// n2n_isnew.first->second = newNode; +// myLastCreatedNodes.Append(newNode); +// srcNodes.Append( node ); +// } +// else { +// //aMesh->MoveNode( node, coord[0], coord[1], coord[2] ); +// aMesh->MoveNode( node, thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz ); +// // node position on shape becomes invalid +// const_cast< SMDS_MeshNode* > ( node )->SetPosition +// ( SMDS_SpacePosition::originSpacePosition() ); +// } +// +// // keep inverse elements +// //if ( !theCopy && !theTargetMesh && needReverse ) { +// // SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator(); +// // while ( invElemIt->more() ) { +// // const SMDS_MeshElement* iel = invElemIt->next(); +// // inverseElemSet.insert( iel ); +// // } +// //} +// } +// } +// +// // either create new elements or reverse mirrored ones +// //if ( !theCopy && !needReverse && !theTargetMesh ) +// if ( !theCopy && !theTargetMesh ) +// return PGroupIDs(); +// +// TIDSortedElemSet::iterator invElemIt = inverseElemSet.begin(); +// for ( ; invElemIt != inverseElemSet.end(); invElemIt++ ) +// theElems.insert( *invElemIt ); +// +// // replicate or reverse elements +// +// enum { +// REV_TETRA = 0, // = nbNodes - 4 +// REV_PYRAMID = 1, // = nbNodes - 4 +// REV_PENTA = 2, // = nbNodes - 4 +// REV_FACE = 3, +// REV_HEXA = 4, // = nbNodes - 4 +// FORWARD = 5 +// }; +// int index[][8] = { +// { 2, 1, 0, 3, 4, 0, 0, 0 }, // REV_TETRA +// { 2, 1, 0, 3, 4, 0, 0, 0 }, // REV_PYRAMID +// { 2, 1, 0, 5, 4, 3, 0, 0 }, // REV_PENTA +// { 2, 1, 0, 3, 0, 0, 0, 0 }, // REV_FACE +// { 2, 1, 0, 3, 6, 5, 4, 7 }, // REV_HEXA +// { 0, 1, 2, 3, 4, 5, 6, 7 } // FORWARD +// }; +// +// for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) +// { +// const SMDS_MeshElement* elem = *itElem; +// if ( !elem || elem->GetType() == SMDSAbs_Node ) +// continue; +// +// int nbNodes = elem->NbNodes(); +// int elemType = elem->GetType(); +// +// if (elem->IsPoly()) { +// // Polygon or Polyhedral Volume +// switch ( elemType ) { +// case SMDSAbs_Face: +// { +// vector poly_nodes (nbNodes); +// int iNode = 0; +// SMDS_ElemIteratorPtr itN = elem->nodesIterator(); +// while (itN->more()) { +// const SMDS_MeshNode* node = +// static_cast(itN->next()); +// TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node); +// if (nodeMapIt == nodeMap.end()) +// break; // not all nodes transformed +// //if (needReverse) { +// // // reverse mirrored faces and volumes +// // poly_nodes[nbNodes - iNode - 1] = (*nodeMapIt).second; +// //} else { +// poly_nodes[iNode] = (*nodeMapIt).second; +// //} +// iNode++; +// } +// if ( iNode != nbNodes ) +// continue; // not all nodes transformed +// +// if ( theTargetMesh ) { +// myLastCreatedElems.Append(aTgtMesh->AddPolygonalFace(poly_nodes)); +// srcElems.Append( elem ); +// } +// else if ( theCopy ) { +// myLastCreatedElems.Append(aMesh->AddPolygonalFace(poly_nodes)); +// srcElems.Append( elem ); +// } +// else { +// aMesh->ChangePolygonNodes(elem, poly_nodes); +// } +// } +// break; +// case SMDSAbs_Volume: +// { +// // ATTENTION: Reversing is not yet done!!! +// const SMDS_VtkVolume* aPolyedre = +// dynamic_cast( elem ); +// if (!aPolyedre) { +// MESSAGE("Warning: bad volumic element"); +// continue; +// } +// +// vector poly_nodes; +// vector quantities; +// +// bool allTransformed = true; +// int nbFaces = aPolyedre->NbFaces(); +// for (int iface = 1; iface <= nbFaces && allTransformed; iface++) { +// int nbFaceNodes = aPolyedre->NbFaceNodes(iface); +// for (int inode = 1; inode <= nbFaceNodes && allTransformed; inode++) { +// const SMDS_MeshNode* node = aPolyedre->GetFaceNode(iface, inode); +// TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node); +// if (nodeMapIt == nodeMap.end()) { +// allTransformed = false; // not all nodes transformed +// } else { +// poly_nodes.push_back((*nodeMapIt).second); +// } +// } +// quantities.push_back(nbFaceNodes); +// } +// if ( !allTransformed ) +// continue; // not all nodes transformed +// +// if ( theTargetMesh ) { +// myLastCreatedElems.Append(aTgtMesh->AddPolyhedralVolume(poly_nodes, quantities)); +// srcElems.Append( elem ); +// } +// else if ( theCopy ) { +// myLastCreatedElems.Append(aMesh->AddPolyhedralVolume(poly_nodes, quantities)); +// srcElems.Append( elem ); +// } +// else { +// aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities); +// } +// } +// break; +// default:; +// } +// continue; +// } +// +// // Regular elements +// int* i = index[ FORWARD ]; +// //if ( needReverse && nbNodes > 2) // reverse mirrored faces and volumes +// // if ( elemType == SMDSAbs_Face ) +// // i = index[ REV_FACE ]; +// // else +// // i = index[ nbNodes - 4 ]; +// +// if(elem->IsQuadratic()) { +// static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; +// i = anIds; +// //if(needReverse) { +// // if(nbNodes==3) { // quadratic edge +// // static int anIds[] = {1,0,2}; +// // i = anIds; +// // } +// // else if(nbNodes==6) { // quadratic triangle +// // static int anIds[] = {0,2,1,5,4,3}; +// // i = anIds; +// // } +// // else if(nbNodes==8) { // quadratic quadrangle +// // static int anIds[] = {0,3,2,1,7,6,5,4}; +// // i = anIds; +// // } +// // else if(nbNodes==10) { // quadratic tetrahedron of 10 nodes +// // static int anIds[] = {0,2,1,3,6,5,4,7,9,8}; +// // i = anIds; +// // } +// // else if(nbNodes==13) { // quadratic pyramid of 13 nodes +// // static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10}; +// // i = anIds; +// // } +// // else if(nbNodes==15) { // quadratic pentahedron with 15 nodes +// // static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13}; +// // i = anIds; +// // } +// // else { // nbNodes==20 - quadratic hexahedron with 20 nodes +// // static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17}; +// // i = anIds; +// // } +// //} +// } +// +// // find transformed nodes +// vector nodes(nbNodes); +// int iNode = 0; +// SMDS_ElemIteratorPtr itN = elem->nodesIterator(); +// while ( itN->more() ) { +// const SMDS_MeshNode* node = +// static_cast( itN->next() ); +// TNodeNodeMap::iterator nodeMapIt = nodeMap.find( node ); +// if ( nodeMapIt == nodeMap.end() ) +// break; // not all nodes transformed +// nodes[ i [ iNode++ ]] = (*nodeMapIt).second; +// } +// if ( iNode != nbNodes ) +// continue; // not all nodes transformed +// +// if ( theTargetMesh ) { +// if ( SMDS_MeshElement* copy = +// targetMeshEditor.AddElement( nodes, elem->GetType(), elem->IsPoly() )) { +// myLastCreatedElems.Append( copy ); +// srcElems.Append( elem ); +// } +// } +// else if ( theCopy ) { +// if ( SMDS_MeshElement* copy = AddElement( nodes, elem->GetType(), elem->IsPoly() )) { +// myLastCreatedElems.Append( copy ); +// srcElems.Append( elem ); +// } +// } +// else { +// // reverse element as it was reversed by transformation +// if ( nbNodes > 2 ) +// aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes ); +// } +// } +// +// PGroupIDs newGroupIDs; +// +// if ( theMakeGroups && theCopy || +// theMakeGroups && theTargetMesh ) { +// string groupPostfix = "scaled"; +// newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh ); +// } +// +// return newGroupIDs; +//} + + //======================================================================= /*! * \brief Create groups of elements made during transformation @@ -5757,9 +6181,8 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher */ const SMDS_MeshNode* FindClosestTo( const gp_Pnt& thePnt ) { - SMDS_MeshNode tgtNode( thePnt.X(), thePnt.Y(), thePnt.Z() ); map dist2Nodes; - myOctreeNode->NodesAround( &tgtNode, dist2Nodes, myHalfLeafSize ); + myOctreeNode->NodesAround( thePnt.Coord(), dist2Nodes, myHalfLeafSize ); if ( !dist2Nodes.empty() ) return dist2Nodes.begin()->second; list nodes; @@ -5775,14 +6198,14 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher list< SMESH_OctreeNode* >::iterator trIt; treeList.push_back( myOctreeNode ); - SMDS_MeshNode pointNode( thePnt.X(), thePnt.Y(), thePnt.Z() ); - bool pointInside = myOctreeNode->isInside( &pointNode, myHalfLeafSize ); + gp_XYZ pointNode( thePnt.X(), thePnt.Y(), thePnt.Z() ); + bool pointInside = myOctreeNode->isInside( pointNode, myHalfLeafSize ); for ( trIt = treeList.begin(); trIt != treeList.end(); ++trIt) { SMESH_OctreeNode* tree = *trIt; if ( !tree->isLeaf() ) // put children to the queue { - if ( pointInside && !tree->isInside( &pointNode, myHalfLeafSize )) continue; + if ( pointInside && !tree->isInside( pointNode, myHalfLeafSize )) continue; SMESH_OctreeNodeIteratorPtr cIt = tree->GetChildrenIterator(); while ( cIt->more() ) treeList.push_back( cIt->next() ); @@ -5818,7 +6241,7 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher const SMDS_MeshNode* closestNode = 0; list::iterator nIt = nodes.begin(); for ( ; nIt != nodes.end(); ++nIt ) { - double sqDist = thePnt.SquareDistance( SMESH_MeshEditor::TNodeXYZ( *nIt ) ); + double sqDist = thePnt.SquareDistance( SMESH_TNodeXYZ( *nIt ) ); if ( minSqDist > sqDist ) { closestNode = *nIt; minSqDist = sqDist; @@ -5873,7 +6296,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() { public: - ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, double tolerance = NodeRadius ); + ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, SMDS_ElemIteratorPtr theElemIt = SMDS_ElemIteratorPtr(), double tolerance = NodeRadius ); void getElementsNearPoint( const gp_Pnt& point, TIDSortedElemSet& foundElems); void getElementsNearLine ( const gp_Ax1& line, TIDSortedElemSet& foundElems); ~ElementBndBoxTree(); @@ -5900,13 +6323,13 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() */ //================================================================================ - ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, double tolerance) + ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, SMDS_ElemIteratorPtr theElemIt, double tolerance) :SMESH_Octree( new SMESH_Octree::Limit( MaxLevel, /*minSize=*/0. )) { int nbElems = mesh.GetMeshInfo().NbElements( elemType ); _elements.reserve( nbElems ); - SMDS_ElemIteratorPtr elemIt = mesh.elementsIterator( elemType ); + SMDS_ElemIteratorPtr elemIt = theElemIt ? theElemIt : mesh.elementsIterator( elemType ); while ( elemIt->more() ) _elements.push_back( new ElementBox( elemIt->next(),tolerance )); @@ -6038,7 +6461,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() _refCount = 1; SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); while ( nIt->more() ) - Add( SMESH_MeshEditor::TNodeXYZ( cast2Node( nIt->next() ))); + Add( SMESH_TNodeXYZ( cast2Node( nIt->next() ))); Enlarge( tolerance ); } @@ -6054,6 +6477,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher { SMESHDS_Mesh* _mesh; + SMDS_ElemIteratorPtr _meshPartIt; ElementBndBoxTree* _ebbTree; SMESH_NodeSearcherImpl* _nodeSearcher; SMDSAbs_ElementType _elementType; @@ -6061,8 +6485,8 @@ struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher bool _outerFacesFound; set _outerFaces; // empty means "no internal faces at all" - SMESH_ElementSearcherImpl( SMESHDS_Mesh& mesh ) - : _mesh(&mesh),_ebbTree(0),_nodeSearcher(0), _tolerance(-1), _outerFacesFound(false) {} + SMESH_ElementSearcherImpl( SMESHDS_Mesh& mesh, SMDS_ElemIteratorPtr elemIt=SMDS_ElemIteratorPtr()) + : _mesh(&mesh),_meshPartIt(elemIt),_ebbTree(0),_nodeSearcher(0),_tolerance(-1),_outerFacesFound(false) {} ~SMESH_ElementSearcherImpl() { if ( _ebbTree ) delete _ebbTree; _ebbTree = 0; @@ -6138,21 +6562,22 @@ double SMESH_ElementSearcherImpl::getTolerance() meshInfo.NbElements( SMDSAbs_ElementType( complexType )) < 1 ) --complexType; if ( complexType == SMDSAbs_All ) return 0; // empty mesh - double elemSize; if ( complexType == int( SMDSAbs_Node )) { SMDS_NodeIteratorPtr nodeIt = _mesh->nodesIterator(); elemSize = 1; if ( meshInfo.NbNodes() > 2 ) - elemSize = SMESH_MeshEditor::TNodeXYZ( nodeIt->next() ).Distance( nodeIt->next() ); + elemSize = SMESH_TNodeXYZ( nodeIt->next() ).Distance( nodeIt->next() ); } else { - const SMDS_MeshElement* elem = - _mesh->elementsIterator( SMDSAbs_ElementType( complexType ))->next(); + SMDS_ElemIteratorPtr elemIt = + _mesh->elementsIterator( SMDSAbs_ElementType( complexType )); + const SMDS_MeshElement* elem = elemIt->next(); SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); - SMESH_MeshEditor::TNodeXYZ n1( cast2Node( nodeIt->next() )); + SMESH_TNodeXYZ n1( cast2Node( nodeIt->next() )); + elemSize = 0; while ( nodeIt->more() ) { double dist = n1.Distance( cast2Node( nodeIt->next() )); @@ -6185,8 +6610,8 @@ bool SMESH_ElementSearcherImpl::getIntersParamOnLine(const gp_Lin& lin int nbNodes = face->IsQuadratic() ? face->NbNodes()/2 : face->NbNodes(); for ( int i = 0; i < nbNodes && nbInts < 2; ++i ) { - GC_MakeSegment edge( SMESH_MeshEditor::TNodeXYZ( face->GetNode( i )), - SMESH_MeshEditor::TNodeXYZ( face->GetNode( (i+1)%nbNodes) )); + GC_MakeSegment edge( SMESH_TNodeXYZ( face->GetNode( i )), + SMESH_TNodeXYZ( face->GetNode( (i+1)%nbNodes) )); anExtCC.Init( lineCurve, edge); if ( anExtCC.NbExtrema() > 0 && anExtCC.LowerDistance() <= tol) { @@ -6246,8 +6671,8 @@ void SMESH_ElementSearcherImpl::findOuterBoundary(const SMDS_MeshElement* outerF seamLinks.insert( link ); // link direction within the outerFace - gp_Vec n1n2( SMESH_MeshEditor::TNodeXYZ( link.node1()), - SMESH_MeshEditor::TNodeXYZ( link.node2())); + gp_Vec n1n2( SMESH_TNodeXYZ( link.node1()), + SMESH_TNodeXYZ( link.node2())); int i1 = outerFace->GetNodeIndex( link.node1() ); int i2 = outerFace->GetNodeIndex( link.node2() ); bool rev = ( abs(i2-i1) == 1 ? i1 > i2 : i2 > i1 ); @@ -6330,7 +6755,7 @@ FindElementsByPoint(const gp_Pnt& point, const SMDS_MeshNode* closeNode = _nodeSearcher->FindClosestTo( point ); if ( !closeNode ) return foundElements.size(); - if ( point.Distance( SMESH_MeshEditor::TNodeXYZ( closeNode )) > tolerance ) + if ( point.Distance( SMESH_TNodeXYZ( closeNode )) > tolerance ) return foundElements.size(); // to far from any node if ( type == SMDSAbs_Node ) @@ -6350,7 +6775,7 @@ FindElementsByPoint(const gp_Pnt& point, if ( !_ebbTree || _elementType != type ) { if ( _ebbTree ) delete _ebbTree; - _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, tolerance ); + _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, _meshPartIt, tolerance ); } TIDSortedElemSet suspectElems; _ebbTree->getElementsNearPoint( point, suspectElems ); @@ -6374,7 +6799,7 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point) if ( !_ebbTree || _elementType != SMDSAbs_Face ) { if ( _ebbTree ) delete _ebbTree; - _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = SMDSAbs_Face ); + _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = SMDSAbs_Face, _meshPartIt ); } // Algo: analyse transition of a line starting at the point through mesh boundary; // try three lines parallel to axis of the coordinate system and perform rough @@ -6402,7 +6827,7 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point) // get face plane gp_XYZ fNorm; if ( !SMESH_Algo::FaceNormal( *face, fNorm, /*normalized=*/false)) continue; - gp_Pln facePlane( SMESH_MeshEditor::TNodeXYZ( (*face)->GetNode(0)), fNorm ); + gp_Pln facePlane( SMESH_TNodeXYZ( (*face)->GetNode(0)), fNorm ); // perform intersection IntAna_IntConicQuad intersection( line, IntAna_Quadric( facePlane )); @@ -6598,7 +7023,7 @@ void SMESH_ElementSearcherImpl::GetElementsNearLine( const gp_Ax1& if ( !_ebbTree || _elementType != type ) { if ( _ebbTree ) delete _ebbTree; - _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type ); + _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, _meshPartIt ); } TIDSortedElemSet suspectFaces; // elements possibly intersecting the line _ebbTree->getElementsNearLine( line, suspectFaces ); @@ -6616,6 +7041,17 @@ SMESH_ElementSearcher* SMESH_MeshEditor::GetElementSearcher() return new SMESH_ElementSearcherImpl( *GetMeshDS() ); } +//======================================================================= +/*! + * \brief Return SMESH_ElementSearcher acting on a sub-set of elements + */ +//======================================================================= + +SMESH_ElementSearcher* SMESH_MeshEditor::GetElementSearcher(SMDS_ElemIteratorPtr elemIt) +{ + return new SMESH_ElementSearcherImpl( *GetMeshDS(), elemIt ); +} + //======================================================================= /*! * \brief Return true if the point is IN or ON of the element @@ -6632,16 +7068,21 @@ bool SMESH_MeshEditor::isOut( const SMDS_MeshElement* element, const gp_Pnt& poi // get ordered nodes vector< gp_XYZ > xyz; + vector nodeList; SMDS_ElemIteratorPtr nodeIt = element->nodesIterator(); - if ( element->IsQuadratic() ) - if (const SMDS_QuadraticFaceOfNodes* f=dynamic_cast(element)) + if ( element->IsQuadratic() ) { + if (const SMDS_VtkFace* f=dynamic_cast(element)) nodeIt = f->interlacedNodesElemIterator(); - else if (const SMDS_QuadraticEdge* e =dynamic_cast(element)) + else if (const SMDS_VtkEdge* e =dynamic_cast(element)) nodeIt = e->interlacedNodesElemIterator(); - + } while ( nodeIt->more() ) - xyz.push_back( TNodeXYZ( cast2Node( nodeIt->next() ))); + { + const SMDS_MeshNode* node = cast2Node( nodeIt->next() ); + xyz.push_back( SMESH_TNodeXYZ(node) ); + nodeList.push_back(node); + } int i, nbNodes = element->NbNodes(); @@ -6650,6 +7091,7 @@ bool SMESH_MeshEditor::isOut( const SMDS_MeshElement* element, const gp_Pnt& poi // compute face normal gp_Vec faceNorm(0,0,0); xyz.push_back( xyz.front() ); + nodeList.push_back( nodeList.front() ); for ( i = 0; i < nbNodes; ++i ) { gp_Vec edge1( xyz[i+1], xyz[i]); @@ -6662,9 +7104,7 @@ bool SMESH_MeshEditor::isOut( const SMDS_MeshElement* element, const gp_Pnt& poi // degenerated face: point is out if it is out of all face edges for ( i = 0; i < nbNodes; ++i ) { - SMDS_MeshNode n1( xyz[i].X(), xyz[i].Y(), xyz[i].Z() ); - SMDS_MeshNode n2( xyz[i+1].X(), xyz[i+1].Y(), xyz[i+1].Z() ); - SMDS_MeshEdge edge( &n1, &n2 ); + SMDS_LinearEdge edge( nodeList[i], nodeList[i+1] ); if ( !isOut( &edge, point, tol )) return false; } @@ -6862,6 +7302,7 @@ int SMESH_MeshEditor::SimplifyFace (const vector faceNode void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) { + MESSAGE("MergeNodes"); myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -6878,10 +7319,12 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) list& nodes = *grIt; list::iterator nIt = nodes.begin(); const SMDS_MeshNode* nToKeep = *nIt; + //MESSAGE("node to keep " << nToKeep->GetID()); for ( ++nIt; nIt != nodes.end(); nIt++ ) { const SMDS_MeshNode* nToRemove = *nIt; nodeNodeMap.insert( TNodeNodeMap::value_type( nToRemove, nToKeep )); if ( nToRemove != nToKeep ) { + //MESSAGE(" node to remove " << nToRemove->GetID()); rmNodeIds.push_back( nToRemove->GetID() ); AddToSameGroups( nToKeep, nToRemove, aMesh ); } @@ -6898,6 +7341,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) set::iterator eIt = elems.begin(); for ( ; eIt != elems.end(); eIt++ ) { const SMDS_MeshElement* elem = *eIt; + //MESSAGE(" ---- inverse elem on node to remove " << elem->GetID()); int nbNodes = elem->NbNodes(); int aShapeId = FindShape( elem ); @@ -6938,8 +7382,11 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) } curNodes[ iCur ] = n; bool isUnique = nodeSet.insert( n ).second; - if ( isUnique ) + if ( isUnique ) { uniqueNodes[ iUnique++ ] = n; + if ( nbRepl && iRepl[ nbRepl-1 ] == iCur ) + --nbRepl; // n do not stick to a node of the elem + } iCur++; } @@ -6947,6 +7394,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) bool isOk = true; int nbUniqueNodes = nodeSet.size(); + //MESSAGE("nbNodes nbUniqueNodes " << nbNodes << " " << nbUniqueNodes); if ( nbNodes != nbUniqueNodes ) { // some nodes stick // Polygons and Polyhedral volumes if (elem->IsPoly()) { @@ -6962,10 +7410,9 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) vector polygons_nodes; vector quantities; int nbNew = SimplifyFace(face_nodes, polygons_nodes, quantities); - if (nbNew > 0) { inode = 0; - for (int iface = 0; iface < nbNew - 1; iface++) { + for (int iface = 0; iface < nbNew; iface++) { int nbNodes = quantities[iface]; vector poly_nodes (nbNodes); for (int ii = 0; ii < nbNodes; ii++, inode++) { @@ -6976,7 +7423,19 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) if (aShapeId) aMesh->SetMeshElementOnShape(newElem, aShapeId); } - aMesh->ChangeElementNodes(elem, &polygons_nodes[inode], quantities[nbNew - 1]); + + MESSAGE("ChangeElementNodes MergeNodes Polygon"); + //aMesh->ChangeElementNodes(elem, &polygons_nodes[inode], quantities[nbNew - 1]); + vector polynodes(polygons_nodes.begin()+inode,polygons_nodes.end()); + int quid =0; + if (nbNew > 0) quid = nbNew - 1; + vector newquant(quantities.begin()+quid, quantities.end()); + const SMDS_MeshElement* newElem = 0; + newElem = aMesh->AddPolyhedralVolume(polynodes, newquant); + myLastCreatedElems.Append(newElem); + if ( aShapeId && newElem ) + aMesh->SetMeshElementOnShape( newElem, aShapeId ); + rmElemIds.push_back(elem->GetID()); } else { rmElemIds.push_back(elem->GetID()); @@ -6989,9 +7448,9 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) rmElemIds.push_back(elem->GetID()); } else { - // each face has to be analized in order to check volume validity - const SMDS_PolyhedralVolumeOfNodes* aPolyedre = - static_cast( elem ); + // each face has to be analyzed in order to check volume validity + const SMDS_VtkVolume* aPolyedre = + dynamic_cast( elem ); if (aPolyedre) { int nbFaces = aPolyedre->NbFaces(); @@ -7019,10 +7478,16 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) } if (quantities.size() > 3) - aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities); - else - rmElemIds.push_back(elem->GetID()); - + { + MESSAGE("ChangeElementNodes MergeNodes Polyhedron"); + //aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities); + const SMDS_MeshElement* newElem = 0; + newElem = aMesh->AddPolyhedralVolume(poly_nodes, quantities); + myLastCreatedElems.Append(newElem); + if ( aShapeId && newElem ) + aMesh->SetMeshElementOnShape( newElem, aShapeId ); + rmElemIds.push_back(elem->GetID()); + } } else { rmElemIds.push_back(elem->GetID()); @@ -7033,9 +7498,10 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) } continue; - } + } // poly element // Regular elements + // TODO not all the possible cases are solved. Find something more generic? switch ( nbNodes ) { case 2: ///////////////////////////////////// EDGE isOk = false; break; @@ -7049,6 +7515,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) isOk = false; else if ( nbRepl == 2 && iRepl[ 1 ] - iRepl[ 0 ] == 2 ) isOk = false; // opposite nodes stick + //MESSAGE("isOk " << isOk); } break; case 6: ///////////////////////////////////// PENTAHEDRON @@ -7113,7 +7580,11 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) // +---+---+ // 0 7 3 isOk = false; + if(nbRepl==2) { + MESSAGE("nbRepl=2: " << iRepl[0] << " " << iRepl[1]); + } if(nbRepl==3) { + MESSAGE("nbRepl=3: " << iRepl[0] << " " << iRepl[1] << " " << iRepl[2]); nbUniqueNodes = 6; if( iRepl[0]==0 && iRepl[1]==1 && iRepl[2]==4 ) { uniqueNodes[0] = curNodes[0]; @@ -7188,14 +7659,20 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) isOk = true; } } + if(nbRepl==4) { + MESSAGE("nbRepl=4: " << iRepl[0] << " " << iRepl[1] << " " << iRepl[2] << " " << iRepl[3]); + } + if(nbRepl==5) { + MESSAGE("nbRepl=5: " << iRepl[0] << " " << iRepl[1] << " " << iRepl[2] << " " << iRepl[3] << " " << iRepl[4]); + } break; } //////////////////////////////////// HEXAHEDRON isOk = false; SMDS_VolumeTool hexa (elem); hexa.SetExternalNormal(); - if ( nbUniqueNodes == 4 && nbRepl == 6 ) { - //////////////////////// ---> tetrahedron + if ( nbUniqueNodes == 4 && nbRepl == 4 ) { + //////////////////////// HEX ---> 1 tetrahedron for ( int iFace = 0; iFace < 6; iFace++ ) { const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] && @@ -7205,12 +7682,9 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) int iOppFace = hexa.GetOppFaceIndex( iFace ); ind = hexa.GetFaceNodesIndices( iOppFace ); int nbStick = 0; - iUnique = 2; // reverse a tetrahedron bottom for ( iCur = 0; iCur < 4 && nbStick < 2; iCur++ ) { if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] ) nbStick++; - else if ( iUnique >= 0 ) - uniqueNodes[ iUnique-- ] = curNodes[ind[ iCur ]]; } if ( nbStick == 1 ) { // ... and the opposite one - into a triangle. @@ -7223,6 +7697,45 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) } } } + else if ( nbUniqueNodes == 6 && nbRepl == 2 ) { + //////////////////////// HEX ---> 1 prism + int nbTria = 0, iTria[3]; + const int *ind; // indices of face nodes + // look for triangular faces + for ( int iFace = 0; iFace < 6 && nbTria < 3; iFace++ ) { + ind = hexa.GetFaceNodesIndices( iFace ); + TIDSortedNodeSet faceNodes; + for ( iCur = 0; iCur < 4; iCur++ ) + faceNodes.insert( curNodes[ind[iCur]] ); + if ( faceNodes.size() == 3 ) + iTria[ nbTria++ ] = iFace; + } + // check if triangles are opposite + if ( nbTria == 2 && iTria[0] == hexa.GetOppFaceIndex( iTria[1] )) + { + isOk = true; + // set nodes of the bottom triangle + ind = hexa.GetFaceNodesIndices( iTria[ 0 ]); + vector indB; + for ( iCur = 0; iCur < 4; iCur++ ) + if ( ind[iCur] != iRepl[0] && ind[iCur] != iRepl[1]) + indB.push_back( ind[iCur] ); + if ( !hexa.IsForward() ) + std::swap( indB[0], indB[2] ); + for ( iCur = 0; iCur < 3; iCur++ ) + uniqueNodes[ iCur ] = curNodes[indB[iCur]]; + // set nodes of the top triangle + const int *indT = hexa.GetFaceNodesIndices( iTria[ 1 ]); + for ( iCur = 0; iCur < 3; ++iCur ) + for ( int j = 0; j < 4; ++j ) + if ( hexa.IsLinked( indB[ iCur ], indT[ j ] )) + { + uniqueNodes[ iCur + 3 ] = curNodes[ indT[ j ]]; + break; + } + } + break; + } else if (nbUniqueNodes == 5 && nbRepl == 4 ) { //////////////////// HEXAHEDRON ---> 2 tetrahedrons for ( int iFace = 0; iFace < 6; iFace++ ) { @@ -7360,6 +7873,10 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) } } } // if ( nbUniqueNodes == 6 && nbRepl == 4 ) + else + { + MESSAGE("MergeNodes() removes hexahedron "<< elem); + } break; } // HEXAHEDRON @@ -7369,11 +7886,12 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) } // if ( nbNodes != nbUniqueNodes ) // some nodes stick - if ( isOk ) { - if (elem->IsPoly() && elem->GetType() == SMDSAbs_Volume) { + if ( isOk ) { // the elem remains valid after sticking nodes + if (elem->IsPoly() && elem->GetType() == SMDSAbs_Volume) + { // Change nodes of polyedre - const SMDS_PolyhedralVolumeOfNodes* aPolyedre = - static_cast( elem ); + const SMDS_VtkVolume* aPolyedre = + dynamic_cast( elem ); if (aPolyedre) { int nbFaces = aPolyedre->NbFaces(); @@ -7397,9 +7915,21 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) aMesh->ChangePolyhedronNodes( elem, poly_nodes, quantities ); } } - else { - // Change regular element or polygon - aMesh->ChangeElementNodes( elem, & uniqueNodes[0], nbUniqueNodes ); + else // replace non-polyhedron elements + { + const SMDSAbs_ElementType etyp = elem->GetType(); + const int elemId = elem->GetID(); + const bool isPoly = (elem->GetEntityType() == SMDSEntity_Polygon); + uniqueNodes.resize(nbUniqueNodes); + + SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0; + + aMesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false); + SMDS_MeshElement* newElem = this->AddElement(uniqueNodes, etyp, isPoly, elemId); + if ( sm && newElem ) + sm->AddElement( newElem ); + if ( elem != newElem ) + ReplaceElemInGroups( elem, newElem, aMesh ); } } else { @@ -7409,10 +7939,10 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) } // loop on elements - // Remove equal nodes and bad elements + // Remove bad elements, then equal nodes (order important) - Remove( rmNodeIds, true ); Remove( rmElemIds, false ); + Remove( rmNodeIds, true ); } @@ -7575,8 +8105,10 @@ SMESH_MeshEditor::FindFaceInSet(const SMDS_MeshNode* n1, const SMDS_MeshElement* face = 0; SMDS_ElemIteratorPtr invElemIt = n1->GetInverseElementIterator(SMDSAbs_Face); + //MESSAGE("n1->GetInverseElementIterator(SMDSAbs_Face) " << invElemIt); while ( invElemIt->more() && !face ) // loop on inverse faces of n1 { + //MESSAGE("in while ( invElemIt->more() && !face )"); const SMDS_MeshElement* elem = invElemIt->next(); if (avoidSet.count( elem )) continue; @@ -7595,10 +8127,11 @@ SMESH_MeshEditor::FindFaceInSet(const SMDS_MeshNode* n1, if ( !face && elem->IsQuadratic()) { // analysis for quadratic elements using all nodes - const SMDS_QuadraticFaceOfNodes* F = - static_cast(elem); + const SMDS_VtkFace* F = + dynamic_cast(elem); + if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); // use special nodes iterator - SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator(); + SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); const SMDS_MeshNode* prevN = cast2Node( anIter->next() ); for ( i1 = -1, i2 = 0; anIter->more() && !face; i1++, i2++ ) { @@ -7682,12 +8215,13 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirst vector nodes(nbNodes+1); if(e->IsQuadratic()) { - const SMDS_QuadraticFaceOfNodes* F = - static_cast(e); + const SMDS_VtkFace* F = + dynamic_cast(e); + if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); // use special nodes iterator - SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator(); + SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); while( anIter->more() ) { - nodes[ iNode++ ] = anIter->next(); + nodes[ iNode++ ] = cast2Node(anIter->next()); } } else { @@ -7857,7 +8391,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, // links of the free border // ------------------------------------------------------------------------- - // 1. Since sewing may brake if there are volumes to split on the side 2, + // 1. Since sewing may break if there are volumes to split on the side 2, // we wont move nodes but just compute new coordinates for them typedef map TNodeXYZMap; TNodeXYZMap nBordXYZ; @@ -7955,12 +8489,13 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, else if ( elem->GetType()==SMDSAbs_Face ) { // --face // retrieve all face nodes and find iPrevNode - an index of the prevSideNode if(elem->IsQuadratic()) { - const SMDS_QuadraticFaceOfNodes* F = - static_cast(elem); + const SMDS_VtkFace* F = + dynamic_cast(elem); + if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); // use special nodes iterator - SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator(); + SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); while( anIter->more() ) { - nodes[ iNode ] = anIter->next(); + nodes[ iNode ] = cast2Node(anIter->next()); if ( nodes[ iNode++ ] == prevSideNode ) iPrevNode = iNode - 1; } @@ -8274,12 +8809,13 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, vector nodes( theFace->NbNodes() ); if(theFace->IsQuadratic()) { - const SMDS_QuadraticFaceOfNodes* F = - static_cast(theFace); + const SMDS_VtkFace* F = + dynamic_cast(theFace); + if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); // use special nodes iterator - SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator(); + SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); while( anIter->more() ) { - const SMDS_MeshNode* n = anIter->next(); + const SMDS_MeshNode* n = cast2Node(anIter->next()); if ( n == theBetweenNode1 ) il1 = iNode; else if ( n == theBetweenNode2 ) @@ -8335,12 +8871,13 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, bool isFLN = false; if(theFace->IsQuadratic()) { - const SMDS_QuadraticFaceOfNodes* F = - static_cast(theFace); + const SMDS_VtkFace* F = + dynamic_cast(theFace); + if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); // use special nodes iterator - SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator(); + SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); while( anIter->more() && !isFLN ) { - const SMDS_MeshNode* n = anIter->next(); + const SMDS_MeshNode* n = cast2Node(anIter->next()); poly_nodes[iNode++] = n; if (n == nodes[il1]) { isFLN = true; @@ -8353,7 +8890,7 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, } // add nodes of face starting from last node of link while ( anIter->more() ) { - poly_nodes[iNode++] = anIter->next(); + poly_nodes[iNode++] = cast2Node(anIter->next()); } } else { @@ -8396,6 +8933,7 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, return; } + SMESHDS_Mesh *aMesh = GetMeshDS(); if( !theFace->IsQuadratic() ) { // put aNodesToInsert between theBetweenNode1 and theBetweenNode2 @@ -8446,7 +8984,6 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, } // create new elements - SMESHDS_Mesh *aMesh = GetMeshDS(); int aShapeId = FindShape( theFace ); i1 = 0; i2 = 1; @@ -8472,8 +9009,16 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, newNodes[ 1 ] = linkNodes[ i2 ]; newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ]; newNodes[ 3 ] = nodes[ i4 ]; - aMesh->ChangeElementNodes( theFace, newNodes, iSplit == iBestQuad ? 4 : 3 ); - } // end if(!theFace->IsQuadratic()) + //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] ); + else + newElem = aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] ); + myLastCreatedElems.Append(newElem); + if ( aShapeId && newElem ) + aMesh->SetMeshElementOnShape( newElem, aShapeId ); +} // end if(!theFace->IsQuadratic()) else { // theFace is quadratic // we have to split theFace on simple triangles and one simple quadrangle int tmp = il1/2; @@ -8500,7 +9045,6 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, // n4 n6 n5 n4 // create new elements - SMESHDS_Mesh *aMesh = GetMeshDS(); int aShapeId = FindShape( theFace ); int n1,n2,n3; @@ -8583,9 +9127,9 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, if ( aShapeId && newElem ) aMesh->SetMeshElementOnShape( newElem, aShapeId ); } - // remove old quadratic face - aMesh->RemoveElement(theFace); } + // remove old face + aMesh->RemoveElement(theFace); } //======================================================================= @@ -8677,7 +9221,7 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode //======================================================================= /*! * \brief Convert elements contained in a submesh to quadratic - * \retval int - nb of checked elements + * \return int - nb of checked elements */ //======================================================================= @@ -8702,7 +9246,7 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh * theSm, vector nodes (elem->begin_nodes(), elem->end_nodes()); if ( elem->GetEntityType() == SMDSEntity_Polyhedra ) - nbNodeInFaces = static_cast( elem )->GetQuanities(); + nbNodeInFaces = static_cast( elem )->GetQuantities(); GetMeshDS()->RemoveFreeElement(elem, theSm, /*fromGroups=*/false); @@ -8760,6 +9304,8 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh * theSm, if( NewElem ) theSm->AddElement( NewElem ); } +// if (!GetMeshDS()->isCompacted()) +// GetMeshDS()->compactMesh(); return nbElem; } @@ -8800,6 +9346,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) if(edge && !edge->IsQuadratic()) { int id = edge->GetID(); + //MESSAGE("edge->GetID() " << id); const SMDS_MeshNode* n1 = edge->GetNode(0); const SMDS_MeshNode* n2 = edge->GetNode(1); @@ -8846,7 +9393,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) int nbNodes = volume->NbNodes(); vector nodes (volume->begin_nodes(), volume->end_nodes()); if ( volume->GetEntityType() == SMDSEntity_Polyhedra ) - nbNodeInFaces = static_cast(volume)->GetQuanities(); + nbNodeInFaces = static_cast(volume)->GetQuantities(); meshDS->RemoveFreeElement(volume, smDS, /*fromGroups=*/false); @@ -8876,17 +9423,157 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) } } - if ( !theForce3d && !getenv("NO_FixQuadraticElements")) + if ( !theForce3d ) { // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion aHelper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh aHelper.FixQuadraticElements(); } } +//================================================================================ +/*! + * \brief Makes given elements quadratic + * \param theForce3d - if true, the medium nodes will be placed in the middle of link + * \param theElements - elements to make quadratic + */ +//================================================================================ + +void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, + TIDSortedElemSet& theElements) +{ + if ( theElements.empty() ) return; + + // we believe that all theElements are of the same type + SMDSAbs_ElementType elemType = (*theElements.begin())->GetType(); + + // get all nodes shared by theElements + TIDSortedNodeSet allNodes; + TIDSortedElemSet::iterator eIt = theElements.begin(); + for ( ; eIt != theElements.end(); ++eIt ) + allNodes.insert( (*eIt)->begin_nodes(), (*eIt)->end_nodes() ); + + // complete theElements with elements of lower dim whose all nodes are in allNodes + + TIDSortedElemSet quadAdjacentElems [ SMDSAbs_NbElementTypes ]; // quadratic adjacent elements + TIDSortedElemSet checkedAdjacentElems [ SMDSAbs_NbElementTypes ]; + TIDSortedNodeSet::iterator nIt = allNodes.begin(); + for ( ; nIt != allNodes.end(); ++nIt ) + { + const SMDS_MeshNode* n = *nIt; + SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(); + while ( invIt->more() ) + { + const SMDS_MeshElement* e = invIt->next(); + if ( e->IsQuadratic() ) + { + quadAdjacentElems[ e->GetType() ].insert( e ); + continue; + } + if ( e->GetType() >= elemType ) + { + continue; // same type of more complex linear element + } + + if ( !checkedAdjacentElems[ e->GetType() ].insert( e ).second ) + continue; // e is already checked + + // check nodes + bool allIn = true; + SMDS_ElemIteratorPtr nodeIt = e->nodesIterator(); + while ( nodeIt->more() && allIn ) + allIn = allNodes.count( cast2Node( nodeIt->next() )); + if ( allIn ) + theElements.insert(e ); + } + } + + SMESH_MesherHelper helper(*myMesh); + helper.SetIsQuadratic( true ); + + // add links of quadratic adjacent elements to the helper + + if ( !quadAdjacentElems[SMDSAbs_Edge].empty() ) + for ( eIt = quadAdjacentElems[SMDSAbs_Edge].begin(); + eIt != quadAdjacentElems[SMDSAbs_Edge].end(); ++eIt ) + { + helper.AddTLinks( static_cast< const SMDS_MeshEdge*> (*eIt) ); + } + if ( !quadAdjacentElems[SMDSAbs_Face].empty() ) + for ( eIt = quadAdjacentElems[SMDSAbs_Face].begin(); + eIt != quadAdjacentElems[SMDSAbs_Face].end(); ++eIt ) + { + helper.AddTLinks( static_cast< const SMDS_MeshFace*> (*eIt) ); + } + if ( !quadAdjacentElems[SMDSAbs_Volume].empty() ) + for ( eIt = quadAdjacentElems[SMDSAbs_Volume].begin(); + eIt != quadAdjacentElems[SMDSAbs_Volume].end(); ++eIt ) + { + helper.AddTLinks( static_cast< const SMDS_MeshVolume*> (*eIt) ); + } + + // make quadratic elements instead of linear ones + + SMESHDS_Mesh* meshDS = GetMeshDS(); + SMESHDS_SubMesh* smDS = 0; + for ( eIt = theElements.begin(); eIt != theElements.end(); ++eIt ) + { + const SMDS_MeshElement* elem = *eIt; + if( elem->IsQuadratic() || elem->NbNodes() < 2 || elem->IsPoly() ) + continue; + + int id = elem->GetID(); + SMDSAbs_ElementType type = elem->GetType(); + vector nodes ( elem->begin_nodes(), elem->end_nodes()); + + if ( !smDS || !smDS->Contains( elem )) + smDS = meshDS->MeshElements( elem->getshapeId() ); + meshDS->RemoveFreeElement(elem, smDS, /*fromGroups=*/false); + + SMDS_MeshElement * newElem = 0; + switch( nodes.size() ) + { + case 4: // cases for most multiple element types go first (for optimization) + if ( type == SMDSAbs_Volume ) + newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d); + else + newElem = helper.AddFace (nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d); + break; + case 8: + newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d); + break; + case 3: + newElem = helper.AddFace (nodes[0], nodes[1], nodes[2], id, theForce3d); + break; + case 2: + newElem = helper.AddEdge(nodes[0], nodes[1], id, theForce3d); + break; + case 5: + newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], id, theForce3d); + break; + case 6: + newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5], id, theForce3d); + break; + default:; + } + ReplaceElemInGroups( elem, newElem, meshDS); + if( newElem && smDS ) + smDS->AddElement( newElem ); + } + + if ( !theForce3d && !getenv("NO_FixQuadraticElements")) + { // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion + helper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh + helper.FixQuadraticElements(); + } +} + //======================================================================= /*! * \brief Convert quadratic elements to linear ones and remove quadratic nodes - * \retval int - nb of checked elements + * \return int - nb of checked elements */ //======================================================================= @@ -8896,7 +9583,6 @@ int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm, { int nbElem = 0; SMESHDS_Mesh* meshDS = GetMeshDS(); - const bool notFromGroups = false; while( theItr->more() ) { @@ -8904,44 +9590,28 @@ int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm, nbElem++; if( elem && elem->IsQuadratic()) { - int id = elem->GetID(); - int nbNodes = elem->NbNodes(); - vector nodes, mediumNodes; - nodes.reserve( nbNodes ); - mediumNodes.reserve( nbNodes ); - - for(int i = 0; i < nbNodes; i++) - { - const SMDS_MeshNode* n = elem->GetNode(i); - - if( elem->IsMediumNode( n ) ) - mediumNodes.push_back( n ); - else - nodes.push_back( n ); - } - if( nodes.empty() ) continue; + int id = elem->GetID(); + int nbCornerNodes = elem->NbCornerNodes(); SMDSAbs_ElementType aType = elem->GetType(); - //remove old quadratic element - meshDS->RemoveFreeElement( elem, theSm, notFromGroups ); + vector nodes( elem->begin_nodes(), elem->end_nodes() ); - SMDS_MeshElement * NewElem = AddElement( nodes, aType, false, id ); - ReplaceElemInGroups(elem, NewElem, meshDS); - if( theSm && NewElem ) - theSm->AddElement( NewElem ); + //remove a quadratic element + if ( !theSm || !theSm->Contains( elem )) + theSm = meshDS->MeshElements( elem->getshapeId() ); + meshDS->RemoveFreeElement( elem, theSm, /*fromGroups=*/false ); // remove medium nodes - vector::iterator nIt = mediumNodes.begin(); - for ( ; nIt != mediumNodes.end(); ++nIt ) { - const SMDS_MeshNode* n = *nIt; - if ( n->NbInverseElements() == 0 ) { - if ( n->GetPosition()->GetShapeId() != theShapeID ) - meshDS->RemoveFreeNode( n, meshDS->MeshElements - ( n->GetPosition()->GetShapeId() )); - else - meshDS->RemoveFreeNode( n, theSm ); - } - } + for ( unsigned i = nbCornerNodes; i < nodes.size(); ++i ) + if ( nodes[i]->NbInverseElements() == 0 ) + meshDS->RemoveFreeNode( nodes[i], theSm ); + + // add a linear element + nodes.resize( nbCornerNodes ); + SMDS_MeshElement * newElem = AddElement( nodes, aType, false, id ); + ReplaceElemInGroups(elem, newElem, meshDS); + if( theSm && newElem ) + theSm->AddElement( newElem ); } } return nbElem; @@ -8951,7 +9621,8 @@ int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm, //function : ConvertFromQuadratic //purpose : //======================================================================= -bool SMESH_MeshEditor::ConvertFromQuadratic() + +bool SMESH_MeshEditor::ConvertFromQuadratic() { int nbCheckedElems = 0; if ( myMesh->HasShapeToMesh() ) @@ -8978,6 +9649,102 @@ bool SMESH_MeshEditor::ConvertFromQuadratic() return true; } +namespace +{ + //================================================================================ + /*! + * \brief Return true if all medium nodes of the element are in the node set + */ + //================================================================================ + + bool allMediumNodesIn(const SMDS_MeshElement* elem, TIDSortedNodeSet& nodeSet ) + { + for ( int i = elem->NbCornerNodes(); i < elem->NbNodes(); ++i ) + if ( !nodeSet.count( elem->GetNode(i) )) + return false; + return true; + } +} + +//================================================================================ +/*! + * \brief Makes given elements linear + */ +//================================================================================ + +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; + TIDSortedElemSet::iterator eIt = theElements.begin(); + for ( ; eIt != theElements.end(); ++eIt ) + { + const SMDS_MeshElement* e = *eIt; + for ( int i = e->NbCornerNodes(); i < e->NbNodes(); ++i ) + mediumNodeIDs.insert( e->GetNode(i)->GetID() ); + } + + // replace given elements by linear ones + typedef SMDS_SetIterator TSetIterator; + SMDS_ElemIteratorPtr elemIt( new TSetIterator( theElements.begin(), theElements.end() )); + removeQuadElem( /*theSm=*/0, elemIt, /*theShapeID=*/0 ); + + // we need to convert remaining elements whose all medium nodes are in mediumNodeIDs + // except those elements sharing medium nodes of quadratic element whose medium nodes + // are not all in mediumNodeIDs + + // get remaining medium nodes + TIDSortedNodeSet mediumNodes; + set::iterator nIdsIt = mediumNodeIDs.begin(); + for ( ; nIdsIt != mediumNodeIDs.end(); ++nIdsIt ) + if ( const SMDS_MeshNode* n = GetMeshDS()->FindNode( *nIdsIt )) + mediumNodes.insert( mediumNodes.end(), n ); + + // find more quadratic elements to convert + TIDSortedElemSet moreElemsToConvert; + TIDSortedNodeSet::iterator nIt = mediumNodes.begin(); + for ( ; nIt != mediumNodes.end(); ++nIt ) + { + SMDS_ElemIteratorPtr invIt = (*nIt)->GetInverseElementIterator(); + while ( invIt->more() ) + { + const SMDS_MeshElement* e = invIt->next(); + if ( e->IsQuadratic() && allMediumNodesIn( e, mediumNodes )) + { + // find a more complex element including e and + // whose medium nodes are not in mediumNodes + bool complexFound = false; + for ( int type = e->GetType() + 1; type < SMDSAbs_0DElement; ++type ) + { + SMDS_ElemIteratorPtr invIt2 = + (*nIt)->GetInverseElementIterator( SMDSAbs_ElementType( type )); + while ( invIt2->more() ) + { + const SMDS_MeshElement* eComplex = invIt2->next(); + if ( eComplex->IsQuadratic() && !allMediumNodesIn( eComplex, mediumNodes)) + { + int nbCommonNodes = SMESH_Algo::GetCommonNodes( e, eComplex ).size(); + if ( nbCommonNodes == e->NbNodes()) + { + complexFound = true; + type = SMDSAbs_NbElementTypes; // to quit from the outer loop + break; + } + } + } + } + if ( !complexFound ) + moreElemsToConvert.insert( e ); + } + } + } + elemIt = SMDS_ElemIteratorPtr + (new TSetIterator( moreElemsToConvert.begin(), moreElemsToConvert.end() )); + removeQuadElem( /*theSm=*/0, elemIt, /*theShapeID=*/0 ); +} + //======================================================================= //function : SewSideElements //purpose : @@ -9008,12 +9775,13 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, // 1. Build set of faces representing each side: // ======================================================================= // a. build set of nodes belonging to faces - // b. complete set of faces: find missing fices whose nodes are in set of nodes + // b. complete set of faces: find missing faces whose nodes are in set of nodes // c. create temporary faces representing side of volumes if correspondent // face does not exist SMESHDS_Mesh* aMesh = GetMeshDS(); - SMDS_Mesh aTmpFacesMesh; + // TODO algoritm not OK with vtkUnstructuredGrid: 2 meshes can't share nodes + //SMDS_Mesh aTmpFacesMesh; // try to use the same mesh set faceSet1, faceSet2; set volSet1, volSet2; set nodeSet1, nodeSet2; @@ -9023,6 +9791,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, TIDSortedElemSet * elemSetPtr[] = { &theSide1, &theSide2 }; int iSide, iFace, iNode; + list tempFaceList; for ( iSide = 0; iSide < 2; iSide++ ) { set * nodeSet = nodeSetPtr[ iSide ]; TIDSortedElemSet * elemSet = elemSetPtr[ iSide ]; @@ -9050,7 +9819,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, // ----------------------------------------------------------- // 1a. Collect nodes of existing faces // and build set of face nodes in order to detect missing - // faces corresponing to sides of volumes + // faces corresponding to sides of volumes // ----------------------------------------------------------- set< set > setOfFaceNodeSet; @@ -9074,7 +9843,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, volSet->insert( elem ); } // ------------------------------------------------------------------------------ - // 1b. Complete set of faces: find missing fices whose nodes are in set of nodes + // 1b. Complete set of faces: find missing faces whose nodes are in set of nodes // ------------------------------------------------------------------------------ for ( nIt = nodeSet->begin(); nIt != nodeSet->end(); nIt++ ) { // loop on nodes of iSide @@ -9142,18 +9911,23 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, if ( !aFreeFace ) { // create a temporary face if ( nbNodes == 3 ) { - aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2] ); + //aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2] ); + aFreeFace = aMesh->AddFace( fNodes[0],fNodes[1],fNodes[2] ); } else if ( nbNodes == 4 ) { - aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] ); + //aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] ); + aFreeFace = aMesh->AddFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] ); } else { vector poly_nodes ( fNodes, & fNodes[nbNodes]); - aFreeFace = aTmpFacesMesh.AddPolygonalFace(poly_nodes); + //aFreeFace = aTmpFacesMesh.AddPolygonalFace(poly_nodes); + aFreeFace = aMesh->AddPolygonalFace(poly_nodes); } } - if ( aFreeFace ) + if ( aFreeFace ) { freeFaceList.push_back( aFreeFace ); + tempFaceList.push_back( aFreeFace ); + } } // loop on faces of a volume @@ -9183,7 +9957,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, fIt++; } else - freeFaceList.erase( fIt++ ); // here fIt++ occures before erase + freeFaceList.erase( fIt++ ); // here fIt++ occurs before erase } if ( freeFaceList.size() > 1 ) { @@ -9267,9 +10041,12 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, if ( faceSet1.size() != faceSet2.size() ) { // delete temporary faces: they are in reverseElements of actual nodes - SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator(); - while ( tmpFaceIt->more() ) - aTmpFacesMesh.RemoveElement( tmpFaceIt->next() ); +// SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator(); +// while ( tmpFaceIt->more() ) +// aTmpFacesMesh.RemoveElement( tmpFaceIt->next() ); +// list::iterator tmpFaceIt = tempFaceList.begin(); +// for (; tmpFaceIt !=tempFaceList.end(); ++tmpFaceIt) +// aMesh->RemoveElement(*tmpFaceIt); MESSAGE("Diff nb of faces"); return SEW_TOPO_DIFF_SETS_OF_ELEMENTS; } @@ -9382,10 +10159,11 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, } } else { // f->IsQuadratic() - const SMDS_QuadraticFaceOfNodes* F = - static_cast(f); + const SMDS_VtkFace* F = + dynamic_cast(f); + if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); // use special nodes iterator - SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator(); + SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); while ( anIter->more() ) { const SMDS_MeshNode* n = static_cast( anIter->next() ); @@ -9425,7 +10203,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, } // check similarity of elements of the sides - if (aResult == SEW_OK && ( face[0] && !face[1] ) || ( !face[0] && face[1] )) { + if (aResult == SEW_OK && (( face[0] && !face[1] ) || ( !face[0] && face[1] ))) { MESSAGE("Correspondent face not found on side " << ( face[0] ? 1 : 0 )); if ( nReplaceMap.size() == 2 ) { // faces on input nodes not found aResult = ( face[0] ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES ); @@ -9524,9 +10302,12 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, // ==================================================================== // delete temporary faces: they are in reverseElements of actual nodes - SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator(); - while ( tmpFaceIt->more() ) - aTmpFacesMesh.RemoveElement( tmpFaceIt->next() ); +// SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator(); +// while ( tmpFaceIt->more() ) +// aTmpFacesMesh.RemoveElement( tmpFaceIt->next() ); +// list::iterator tmpFaceIt = tempFaceList.begin(); +// for (; tmpFaceIt !=tempFaceList.end(); ++tmpFaceIt) +// aMesh->RemoveElement(*tmpFaceIt); if ( aResult != SEW_OK) return aResult; @@ -9560,7 +10341,21 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, // elemIDsToRemove.push_back( e->GetID() ); // else if ( nbReplaced ) - aMesh->ChangeElementNodes( e, & nodes[0], nbNodes ); + { + SMDSAbs_ElementType etyp = e->GetType(); + SMDS_MeshElement* newElem = this->AddElement(nodes, etyp, false); + if (newElem) + { + myLastCreatedElems.Append(newElem); + AddToSameGroups(newElem, e, aMesh); + int aShapeId = e->getshapeId(); + if ( aShapeId ) + { + aMesh->SetMeshElementOnShape( newElem, aShapeId ); + } + } + aMesh->RemoveElement(e); + } } } @@ -9579,7 +10374,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, * \param theSecondNode1 - a boundary node of set 1 linked with theFirstNode1 * \param theSecondNode2 - a node of set 2 corresponding to theSecondNode1 * \param nReplaceMap - output map of corresponding nodes - * \retval bool - is a success or not + * \return bool - is a success or not */ //================================================================================ @@ -9796,6 +10591,7 @@ bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh* theMeshDS, const SMDS_MeshNode* >& theNodeNodeMap, const bool theIsDoubleElem ) { + MESSAGE("doubleNodes"); // iterate on through element and duplicate them (by nodes duplication) bool res = false; TIDSortedElemSet::const_iterator elemItr = theElems.begin(); @@ -9833,8 +10629,10 @@ bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh* theMeshDS, if ( theIsDoubleElem ) AddElement(newNodes, anElem->GetType(), anElem->IsPoly()); else + { + MESSAGE("ChangeElementNodes"); theMeshDS->ChangeElementNodes( anElem, &newNodes[ 0 ], anElem->NbNodes() ); - + } res = true; } return res; @@ -9854,6 +10652,7 @@ bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh* theMeshDS, bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, const std::list< int >& theListOfModifiedElems ) { + MESSAGE("DoubleNodes"); myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -9926,7 +10725,10 @@ bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, const SMDS_MeshElement* anElem = anElemToNodesIter->first; vector aNodeArr = anElemToNodesIter->second; if ( anElem ) + { + MESSAGE("ChangeElementNodes"); aMeshDS->ChangeElementNodes( anElem, &aNodeArr[ 0 ], anElem->NbNodes() ); + } } return true; @@ -9949,7 +10751,7 @@ namespace { gp_XYZ centerXYZ (0, 0, 0); SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator(); while (aNodeItr->more()) - centerXYZ += SMESH_MeshEditor::TNodeXYZ(cast2Node( aNodeItr->next())); + centerXYZ += SMESH_TNodeXYZ(cast2Node( aNodeItr->next())); gp_Pnt aPnt = centerXYZ / theElem->NbNodes(); theClassifier.Perform(aPnt, theTol); @@ -10054,6 +10856,655 @@ bool SMESH_MeshEditor::DoubleNodesInRegion( const TIDSortedElemSet& theElems, return DoubleNodes( theElems, theNodesNot, anAffected ); } +/*! + * \brief compute an oriented angle between two planes defined by four points. + * The vector (p0,p1) defines the intersection of the 2 planes (p0,p1,g1) and (p0,p1,g2) + * @param p0 base of the rotation axe + * @param p1 extremity of the rotation axe + * @param g1 belongs to the first plane + * @param g2 belongs to the second plane + */ +double SMESH_MeshEditor::OrientedAngle(const gp_Pnt& p0, const gp_Pnt& p1, const gp_Pnt& g1, const gp_Pnt& g2) +{ +// MESSAGE(" p0: " << p0.X() << " " << p0.Y() << " " << p0.Z()); +// MESSAGE(" p1: " << p1.X() << " " << p1.Y() << " " << p1.Z()); +// MESSAGE(" g1: " << g1.X() << " " << g1.Y() << " " << g1.Z()); +// MESSAGE(" g2: " << g2.X() << " " << g2.Y() << " " << g2.Z()); + gp_Vec vref(p0, p1); + gp_Vec v1(p0, g1); + gp_Vec v2(p0, g2); + gp_Vec n1 = vref.Crossed(v1); + gp_Vec n2 = vref.Crossed(v2); + return n2.AngleWithRef(n1, vref); +} + +/*! + * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand. + * The list of groups must describe a partition of the mesh volumes. + * The nodes of the internal faces at the boundaries of the groups are doubled. + * In option, the internal faces are replaced by flat elements. + * Triangles are transformed in prisms, and quadrangles in hexahedrons. + * The flat elements are stored in groups of volumes. + * @param theElems - list of groups of volumes, where a group of volume is a set of + * SMDS_MeshElements sorted by Id. + * @param createJointElems - if TRUE, create the elements + * @return TRUE if operation has been completed successfully, FALSE otherwise + */ +bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector& theElems, + bool createJointElems) +{ + MESSAGE("----------------------------------------------"); + MESSAGE("SMESH_MeshEditor::doubleNodesOnGroupBoundaries"); + MESSAGE("----------------------------------------------"); + + SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS(); + meshDS->BuildDownWardConnectivity(true); + CHRONO(50); + SMDS_UnstructuredGrid *grid = meshDS->getGrid(); + + // --- build the list of faces shared by 2 domains (group of elements), with their domain and volume indexes + // build the list of cells with only a node or an edge on the border, with their domain and volume indexes + // build the list of nodes shared by 2 or more domains, with their domain indexes + + std::map, DownIdCompare> faceDomains; // face --> (id domain --> id volume) + std::mapcelldom; // 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(); + + for (int idom = 0; idom < theElems.size(); idom++) + { + + // --- build a map (face to duplicate --> volume to modify) + // with all the faces shared by 2 domains (group of elements) + // and corresponding volume of this domain, for each shared face. + // a volume has a face shared by 2 domains if it has a neighbor which is not in is domain. + + const TIDSortedElemSet& domain = theElems[idom]; + TIDSortedElemSet::const_iterator elemItr = domain.begin(); + for (; elemItr != domain.end(); ++elemItr) + { + SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr; + if (!anElem) + continue; + int vtkId = anElem->getVtkId(); + int neighborsVtkIds[NBMAXNEIGHBORS]; + int downIds[NBMAXNEIGHBORS]; + unsigned char downTypes[NBMAXNEIGHBORS]; + int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId); + for (int n = 0; n < nbNeighbors; n++) + { + int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]); + const SMDS_MeshElement* elem = meshDS->FindElement(smdsId); + if (! domain.count(elem)) // neighbor is in another domain : face is shared + { + DownIdType face(downIds[n], downTypes[n]); + if (!faceDomains.count(face)) + faceDomains[face] = emptyMap; // create an empty entry for face + if (!faceDomains[face].count(idom)) + { + faceDomains[face][idom] = vtkId; // volume associated to face in this domain + celldom[vtkId] = idom; + } + } + } + } + } + + //MESSAGE("Number of shared faces " << faceDomains.size()); + std::map, DownIdCompare>::iterator itface; + + // --- explore the shared faces domain by domain, + // explore the nodes of the face and see if they belong to a cell in the domain, + // which has only a node or an edge on the border (not a shared face) + + for (int idomain = 0; idomain < theElems.size(); idomain++) + { + const TIDSortedElemSet& domain = theElems[idomain]; + itface = faceDomains.begin(); + for (; itface != faceDomains.end(); ++itface) + { + std::map domvol = itface->second; + if (!domvol.count(idomain)) + continue; + DownIdType face = itface->first; + //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); + std::set cells; + cells.clear(); + vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId); + for (int i=0; iFindElement(GetMeshDS()->fromVtkToSmds(vtkId)); + if (!domain.count(anElem)) + continue; + int vtkType = grid->GetCellType(vtkId); + int downId = grid->CellIdToDownId(vtkId); + if (downId < 0) + { + MESSAGE("doubleNodesOnGroupBoundaries: internal algorithm problem"); + continue; // not OK at this stage of the algorithm: + //no cells created after BuildDownWardConnectivity + } + DownIdType aCell(downId, vtkType); + if (celldom.count(vtkId)) + continue; + cellDomains[aCell][idomain] = vtkId; + celldom[vtkId] = idomain; + } + } + } + } + + // --- explore the shared faces domain by domain, to duplicate the nodes in a coherent way + // for each shared face, get the nodes + // for each node, for each domain of the face, create a clone of the node + + // --- edges at the intersection of 3 or 4 domains, with the order of domains to build + // junction elements of type prism or hexa. the key is the pair of nodesId (lower first) + // the value is the ordered domain ids. (more than 4 domains not taken into account) + + std::map, std::vector > edgesMultiDomains; // nodes of edge --> ordered domains + std::map > mutipleNodes; // nodes muti domains with domain order + + for (int idomain = 0; idomain < theElems.size(); idomain++) + { + itface = faceDomains.begin(); + for (; itface != faceDomains.end(); ++itface) + { + std::map domvol = itface->second; + if (!domvol.count(idomain)) + continue; + DownIdType face = itface->first; + //MESSAGE(" --- face " << face.cellId); + std::set oldNodes; + oldNodes.clear(); + grid->GetNodeIds(oldNodes, face.cellId, face.cellType); + bool isMultipleDetected = false; + std::set::iterator itn = oldNodes.begin(); + for (; itn != oldNodes.end(); ++itn) + { + int oldId = *itn; + //MESSAGE(" node " << oldId); + if (!nodeDomains.count(oldId)) + nodeDomains[oldId] = emptyMap; // create an empty entry for node + if (nodeDomains[oldId].empty()) + nodeDomains[oldId][idomain] = oldId; // keep the old node in the first domain + std::map::iterator itdom = domvol.begin(); + for (; itdom != domvol.end(); ++itdom) + { + int idom = itdom->first; + //MESSAGE(" domain " << idom); + if (!nodeDomains[oldId].count(idom)) // --- node to clone + { + if (nodeDomains[oldId].size() >= 2) // a multiple node + { + vector orderedDoms; + //MESSAGE("multiple node " << oldId); + isMultipleDetected =true; + if (mutipleNodes.count(oldId)) + orderedDoms = mutipleNodes[oldId]; + else + { + map::iterator it = nodeDomains[oldId].begin(); + for (; it != nodeDomains[oldId].end(); ++it) + orderedDoms.push_back(it->first); + } + orderedDoms.push_back(idom); // TODO order ==> push_front or back + //stringstream txt; + //for (int i=0; iGetPoint(oldId); + SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]); + int newId = newNode->getVtkId(); + nodeDomains[oldId][idom] = newId; // cloned node for other domains + //MESSAGE(" newNode " << newId << " oldNode " << oldId << " size=" <= 3) + { + //MESSAGE("confirm multiple node " << oldId); + isMultipleDetected =true; + } + } + } + if (isMultipleDetected) // check if an edge of the face is shared between 3 or more domains + { + //MESSAGE("multiple Nodes detected on a shared face"); + int downId = itface->first.cellId; + unsigned char cellType = itface->first.cellType; + int nbEdges = grid->getDownArray(cellType)->getNumberOfDownCells(downId); + const int *downEdgeIds = grid->getDownArray(cellType)->getDownCells(downId); + const unsigned char* edgeType = grid->getDownArray(cellType)->getDownTypes(downId); + for (int ie =0; ie < nbEdges; ie++) + { + int nodes[3]; + int nbNodes = grid->getDownArray(edgeType[ie])->getNodes(downEdgeIds[ie], nodes); + if (mutipleNodes.count(nodes[0]) && mutipleNodes.count(nodes[nbNodes-1])) + { + vector vn0 = mutipleNodes[nodes[0]]; + vector vn1 = mutipleNodes[nodes[nbNodes - 1]]; + sort( vn0.begin(), vn0.end() ); + sort( vn1.begin(), vn1.end() ); + if (vn0 == vn1) + { + //MESSAGE(" detect edgesMultiDomains " << nodes[0] << " " << nodes[nbNodes - 1]); + double *coords = grid->GetPoint(nodes[0]); + gp_Pnt p0(coords[0], coords[1], coords[2]); + coords = grid->GetPoint(nodes[nbNodes - 1]); + gp_Pnt p1(coords[0], coords[1], coords[2]); + gp_Pnt gref; + int vtkVolIds[1000]; // an edge can belong to a lot of volumes + map domvol; // domain --> a volume with the edge + map angleDom; // oriented angles between planes defined by edge and volume centers + int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]); + for (int id=0; id < vn0.size(); id++) + { + int idom = vn0[id]; + for (int ivol=0; ivolfromVtkToSmds(vtkVolIds[ivol]); + SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId); + if (theElems[idom].count(elem)) + { + SMDS_VtkVolume* svol = dynamic_cast(elem); + domvol[idom] = svol; + //MESSAGE(" domain " << idom << " volume " << elem->GetID()); + double values[3]; + vtkIdType npts = 0; + vtkIdType* pts = 0; + grid->GetCellPoints(vtkVolIds[ivol], npts, pts); + SMDS_VtkVolume::gravityCenter(grid, pts, npts, values); + if (id ==0) + { + gref.SetXYZ(gp_XYZ(values[0], values[1], values[2])); + angleDom[idom] = 0; + } + else + { + gp_Pnt g(values[0], values[1], values[2]); + angleDom[idom] = OrientedAngle(p0, p1, gref, g); // -pisecond << " angle " << ib->first); + } + for (int ino = 0; ino < nbNodes; ino++) + vnodes.push_back(nodes[ino]); + edgesMultiDomains[vnodes] = vdom; // nodes vector --> ordered domains + } + } + } + } + } + } + + // --- iterate on shared faces (volumes to modify, face to extrude) + // get node id's of the face (id SMDS = id VTK) + // create flat element with old and new nodes if requested + + // --- new quad nodes on flat quad elements: oldId --> ((domain1 X domain2) --> newId) + // (domain1 X domain2) = domain1 + MAXINT*domain2 + + std::map > nodeQuadDomains; + std::map mapOfJunctionGroups; + + if (createJointElems) + { + itface = faceDomains.begin(); + for (; itface != faceDomains.end(); ++itface) + { + DownIdType face = itface->first; + std::set oldNodes; + std::set::iterator itn; + oldNodes.clear(); + grid->GetNodeIds(oldNodes, face.cellId, face.cellType); + + std::map domvol = itface->second; + std::map::iterator itdom = domvol.begin(); + int dom1 = itdom->first; + int vtkVolId = itdom->second; + itdom++; + int dom2 = itdom->first; + SMDS_MeshVolume *vol = grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains, + nodeQuadDomains); + stringstream grpname; + grpname << "j_"; + if (dom1 < dom2) + grpname << dom1 << "_" << dom2; + else + grpname << dom2 << "_" << dom1; + int idg; + string namegrp = grpname.str(); + if (!mapOfJunctionGroups.count(namegrp)) + mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg); + SMESHDS_Group *sgrp = dynamic_cast(mapOfJunctionGroups[namegrp]->GetGroupDS()); + if (sgrp) + sgrp->Add(vol->GetID()); + } + } + + // --- create volumes on multiple domain intersection if requested + // iterate on edgesMultiDomains + + if (createJointElems) + { + std::map, std::vector >::iterator ite = edgesMultiDomains.begin(); + for (; ite != edgesMultiDomains.end(); ++ite) + { + vector nodes = ite->first; + vector orderDom = ite->second; + vector orderedNodes; + if (nodes.size() == 2) + { + //MESSAGE(" use edgesMultiDomains " << nodes[0] << " " << nodes[1]); + for (int ino=0; ino < nodes.size(); ino++) + if (orderDom.size() == 3) + for (int idom = 0; idom =0; idom--) + orderedNodes.push_back( nodeDomains[nodes[ino]][orderDom[idom]] ); + SMDS_MeshVolume* vol = this->GetMeshDS()->AddVolumeFromVtkIds(orderedNodes); + + stringstream grpname; + grpname << "mj_"; + grpname << 0 << "_" << 0; + int idg; + string namegrp = grpname.str(); + if (!mapOfJunctionGroups.count(namegrp)) + mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg); + SMESHDS_Group *sgrp = dynamic_cast(mapOfJunctionGroups[namegrp]->GetGroupDS()); + if (sgrp) + sgrp->Add(vol->GetID()); + } + else + { + //MESSAGE("Quadratic multiple joints not implemented"); + // TODO quadratic nodes + } + } + } + + // --- list the explicit faces and edges of the mesh that need to be modified, + // i.e. faces and edges built with one or more duplicated nodes. + // associate these faces or edges to their corresponding domain. + // only the first domain found is kept when a face or edge is shared + + std::map, DownIdCompare> faceOrEdgeDom; // cellToModify --> (id domain --> id cell) + std::map feDom; // vtk id of cell to modify --> id domain + faceOrEdgeDom.clear(); + feDom.clear(); + + for (int idomain = 0; idomain < theElems.size(); idomain++) + { + std::map >::const_iterator itnod = nodeDomains.begin(); + for (; itnod != nodeDomains.end(); ++itnod) + { + int oldId = itnod->first; + //MESSAGE(" node " << oldId); + vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId); + for (int i = 0; i < l.ncells; i++) + { + int vtkId = l.cells[i]; + int vtkType = grid->GetCellType(vtkId); + int downId = grid->CellIdToDownId(vtkId); + if (downId < 0) + continue; // new cells: not to be modified + DownIdType aCell(downId, vtkType); + int volParents[1000]; + int nbvol = grid->GetParentVolumes(volParents, vtkId); + 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); + } + } + } + } + + // --- iterate on shared faces (volumes to modify, face to extrude) + // get node id's of the face + // replace old nodes by new nodes in volumes, and update inverse connectivity + + std::map, DownIdCompare>* maps[3] = {&faceDomains, &cellDomains, &faceOrEdgeDom}; + for (int m=0; m<3; m++) + { + std::map, DownIdCompare>* amap = maps[m]; + itface = (*amap).begin(); + for (; itface != (*amap).end(); ++itface) + { + DownIdType face = itface->first; + 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; + + std::map domvol = itface->second; + std::map::iterator itdom = domvol.begin(); + for (; itdom != domvol.end(); ++itdom) + { + int idom = itdom->first; + int vtkVolId = itdom->second; + //MESSAGE("modify nodes of cell " << this->GetMeshDS()->fromVtkToSmds(vtkVolId) << " domain " << idom); + localClonedNodeIds.clear(); + for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn) + { + int oldId = *itn; + if (nodeDomains[oldId].count(idom)) + { + localClonedNodeIds[oldId] = nodeDomains[oldId][idom]; + //MESSAGE(" node " << oldId << " --> " << localClonedNodeIds[oldId]); + } + } + meshDS->ModifyCellNodes(vtkVolId, localClonedNodeIds); + } + } + } + + meshDS->CleanDownWardConnectivity(); // Mesh has been modified, downward connectivity is no more usable, free memory + grid->BuildLinks(); + + CHRONOSTOP(50); + counters::stats(); + return true; +} + +/*! + * \brief Double nodes on some external faces and create flat elements. + * Flat elements are mainly used by some types of mechanic calculations. + * + * Each group of the list must be constituted of faces. + * Triangles are transformed in prisms, and quadrangles in hexahedrons. + * @param theElems - list of groups of faces, where a group of faces is a set of + * SMDS_MeshElements sorted by Id. + * @return TRUE if operation has been completed successfully, FALSE otherwise + */ +bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector& theElems) +{ + MESSAGE("-------------------------------------------------"); + MESSAGE("SMESH_MeshEditor::CreateFlatElementsOnFacesGroups"); + MESSAGE("-------------------------------------------------"); + + SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS(); + + // --- For each group of faces + // duplicate the nodes, create a flat element based on the face + // replace the nodes of the faces by their clones + + std::map clonedNodes; + std::map intermediateNodes; + clonedNodes.clear(); + intermediateNodes.clear(); + std::map mapOfJunctionGroups; + mapOfJunctionGroups.clear(); + + for (int idom = 0; idom < theElems.size(); idom++) + { + const TIDSortedElemSet& domain = theElems[idom]; + TIDSortedElemSet::const_iterator elemItr = domain.begin(); + for (; elemItr != domain.end(); ++elemItr) + { + SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr; + SMDS_MeshFace* aFace = dynamic_cast (anElem); + if (!aFace) + continue; + // MESSAGE("aFace=" << aFace->GetID()); + bool isQuad = aFace->IsQuadratic(); + vector ln0, ln1, ln2, ln3, ln4; + + // --- clone the nodes, create intermediate nodes for non medium nodes of a quad face + + SMDS_ElemIteratorPtr nodeIt = aFace->nodesIterator(); + while (nodeIt->more()) + { + const SMDS_MeshNode* node = static_cast (nodeIt->next()); + bool isMedium = isQuad && (aFace->IsMediumNode(node)); + if (isMedium) + ln2.push_back(node); + else + ln0.push_back(node); + + const SMDS_MeshNode* clone = 0; + if (!clonedNodes.count(node)) + { + clone = meshDS->AddNode(node->X(), node->Y(), node->Z()); + clonedNodes[node] = clone; + } + else + clone = clonedNodes[node]; + + if (isMedium) + ln3.push_back(clone); + else + ln1.push_back(clone); + + const SMDS_MeshNode* inter = 0; + if (isQuad && (!isMedium)) + { + if (!intermediateNodes.count(node)) + { + inter = meshDS->AddNode(node->X(), node->Y(), node->Z()); + intermediateNodes[node] = inter; + } + else + inter = intermediateNodes[node]; + ln4.push_back(inter); + } + } + + // --- extrude the face + + vector ln; + SMDS_MeshVolume* vol = 0; + vtkIdType aType = aFace->GetVtkType(); + switch (aType) + { + case VTK_TRIANGLE: + vol = meshDS->AddVolume(ln0[2], ln0[1], ln0[0], ln1[2], ln1[1], ln1[0]); + // MESSAGE("vol prism " << vol->GetID()); + ln.push_back(ln1[0]); + ln.push_back(ln1[1]); + ln.push_back(ln1[2]); + break; + case VTK_QUAD: + vol = meshDS->AddVolume(ln0[3], ln0[2], ln0[1], ln0[0], ln1[3], ln1[2], ln1[1], ln1[0]); + // MESSAGE("vol hexa " << vol->GetID()); + ln.push_back(ln1[0]); + ln.push_back(ln1[1]); + ln.push_back(ln1[2]); + ln.push_back(ln1[3]); + break; + case VTK_QUADRATIC_TRIANGLE: + vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln0[0], ln0[1], ln0[2], ln3[0], ln3[1], ln3[2], + ln2[0], ln2[1], ln2[2], ln4[0], ln4[1], ln4[2]); + // MESSAGE("vol quad prism " << vol->GetID()); + ln.push_back(ln1[0]); + ln.push_back(ln1[1]); + ln.push_back(ln1[2]); + ln.push_back(ln3[0]); + ln.push_back(ln3[1]); + ln.push_back(ln3[2]); + break; + case VTK_QUADRATIC_QUAD: +// vol = meshDS->AddVolume(ln0[0], ln0[1], ln0[2], ln0[3], ln1[0], ln1[1], ln1[2], ln1[3], +// ln2[0], ln2[1], ln2[2], ln2[3], ln3[0], ln3[1], ln3[2], ln3[3], +// ln4[0], ln4[1], ln4[2], ln4[3]); + vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln1[3], ln0[0], ln0[1], ln0[2], ln0[3], + ln3[0], ln3[1], ln3[2], ln3[3], ln2[0], ln2[1], ln2[2], ln2[3], + ln4[0], ln4[1], ln4[2], ln4[3]); + // MESSAGE("vol quad hexa " << vol->GetID()); + ln.push_back(ln1[0]); + ln.push_back(ln1[1]); + ln.push_back(ln1[2]); + ln.push_back(ln1[3]); + ln.push_back(ln3[0]); + ln.push_back(ln3[1]); + ln.push_back(ln3[2]); + ln.push_back(ln3[3]); + break; + case VTK_POLYGON: + break; + default: + break; + } + + if (vol) + { + stringstream grpname; + grpname << "jf_"; + grpname << idom; + int idg; + string namegrp = grpname.str(); + if (!mapOfJunctionGroups.count(namegrp)) + mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg); + SMESHDS_Group *sgrp = dynamic_cast(mapOfJunctionGroups[namegrp]->GetGroupDS()); + if (sgrp) + sgrp->Add(vol->GetID()); + } + + // --- modify the face + + aFace->ChangeNodes(&ln[0], ln.size()); + } + } + return true; +} + //================================================================================ /*! * \brief Generates skin mesh (containing 2D cells) from 3D mesh @@ -10122,17 +11573,24 @@ namespace * \param group - a group to store created boundary elements in * \param targetMesh - a mesh to store created boundary elements in * \param toCopyElements - if true, the checked elements will be copied into the targetMesh - * \param toCopyExistingBondary - if true, not only new but also pre-existing + * \param toCopyExistingBoundary - if true, not only new but also pre-existing * boundary elements will be copied into the targetMesh + * \param toAddExistingBondary - if true, not only new but also pre-existing + * boundary elements will be added into the new group + * \param aroundElements - if true, elements will be created on boundary of given + * elements else, on boundary of the whole mesh. + * \return nb of added boundary elements */ //================================================================================ -void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, - Bnd_Dimension dimension, - SMESH_Group* group/*=0*/, - SMESH_Mesh* targetMesh/*=0*/, - bool toCopyElements/*=false*/, - bool toCopyExistingBondary/*=false*/) +int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, + Bnd_Dimension dimension, + SMESH_Group* group/*=0*/, + SMESH_Mesh* targetMesh/*=0*/, + bool toCopyElements/*=false*/, + bool toCopyExistingBoundary/*=false*/, + bool toAddExistingBondary/*= false*/, + bool aroundElements/*= false*/) { SMDSAbs_ElementType missType = (dimension == BND_2DFROM3D) ? SMDSAbs_Face : SMDSAbs_Edge; SMDSAbs_ElementType elemType = (dimension == BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume; @@ -10141,13 +11599,20 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, throw SALOME_Exception(LOCALIZED("wrong element type")); if ( !targetMesh ) - toCopyElements = toCopyExistingBondary = false; + toCopyElements = toCopyExistingBoundary = false; SMESH_MeshEditor tgtEditor( targetMesh ? targetMesh : myMesh ); SMESHDS_Mesh* aMesh = GetMeshDS(), *tgtMeshDS = tgtEditor.GetMeshDS(); + int nbAddedBnd = 0; + + // editor adding present bnd elements and optionally holding elements to add to the group + SMESH_MeshEditor* presentEditor; + SMESH_MeshEditor tgtEditor2( tgtEditor.GetMesh() ); + presentEditor = toAddExistingBondary ? &tgtEditor : &tgtEditor2; SMDS_VolumeTool vTool; - TIDSortedElemSet emptySet, avoidSet; + TIDSortedElemSet avoidSet; + const TIDSortedElemSet emptySet, *elemSet = aroundElements ? &elements : &emptySet; int inode; typedef vector TConnectivity; @@ -10163,18 +11628,22 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, const SMDS_MeshElement* elem = eIt->next(); const int iQuad = elem->IsQuadratic(); + // ------------------------------------------------------------------------------------ // 1. For an elem, get present bnd elements and connectivities of missing bnd elements + // ------------------------------------------------------------------------------------ vector presentBndElems; vector missingBndElems; TConnectivity nodes; if ( vTool.Set(elem) ) // 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)) + if ( !vTool.IsFreeFace(iface, &otherVol) && + ( !aroundElements || elements.count( otherVol ))) continue; - int nbFaceNodes = vTool.NbFaceNodes(iface); + const int nbFaceNodes = vTool.NbFaceNodes(iface); const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface); if ( missType == SMDSAbs_Edge ) // boundary edges { @@ -10203,6 +11672,21 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, presentBndElems.push_back( f ); else missingBndElems.push_back( nodes ); + + if ( targetMesh != myMesh ) + { + // add 1D elements on face boundary to be added to a new mesh + const SMDS_MeshElement* edge; + for ( inode = 0; inode < nbFaceNodes; inode += 1+iQuad) + { + if ( iQuad ) + edge = aMesh->FindEdge( nn[inode], nn[inode+1], nn[inode+2]); + else + edge = aMesh->FindEdge( nn[inode], nn[inode+1]); + if ( edge && avoidSet.insert( edge ).second ) + presentBndElems.push_back( edge ); + } + } } } } @@ -10215,7 +11699,7 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, { nodes[0] = elem->GetNode(i); nodes[1] = elem->GetNode((i+1)%nbNodes); - if ( FindFaceInSet( nodes[0], nodes[1], emptySet, avoidSet)) + if ( FindFaceInSet( nodes[0], nodes[1], *elemSet, avoidSet)) continue; // not free link //if ( iQuad ) @@ -10228,40 +11712,60 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, } } + // --------------------------------- // 2. Add missing boundary elements + // --------------------------------- if ( targetMesh != myMesh ) // instead of making a map of nodes in this mesh and targetMesh, - // we create nodes with same IDs. We can renumber them later, if needed + // we create nodes with same IDs. for ( int i = 0; i < missingBndElems.size(); ++i ) { TConnectivity& srcNodes = missingBndElems[i]; TConnectivity nodes( srcNodes.size() ); for ( inode = 0; inode < nodes.size(); ++inode ) nodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] ); + if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes, + missType, + /*noMedium=*/true)) + continue; tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4); + ++nbAddedBnd; } else for ( int i = 0; i < missingBndElems.size(); ++i ) { - TConnectivity& nodes = missingBndElems[i]; + TConnectivity& nodes = missingBndElems[i]; + if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes, + missType, + /*noMedium=*/true)) + continue; tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4); + ++nbAddedBnd; } + // ---------------------------------- // 3. Copy present boundary elements - if ( toCopyExistingBondary ) + // ---------------------------------- + if ( toCopyExistingBoundary ) for ( int i = 0 ; i < presentBndElems.size(); ++i ) { const SMDS_MeshElement* e = presentBndElems[i]; TConnectivity nodes( e->NbNodes() ); for ( inode = 0; inode < nodes.size(); ++inode ) nodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(inode) ); - tgtEditor.AddElement(nodes, missType, e->IsPoly()); - // leave only missing elements in tgtEditor.myLastCreatedElems - tgtEditor.myLastCreatedElems.Remove( tgtEditor.myLastCreatedElems.Size() ); + presentEditor->AddElement(nodes, e->GetType(), e->IsPoly()); + } + else // store present elements to add them to a group + for ( int i = 0 ; i < presentBndElems.size(); ++i ) + { + presentEditor->myLastCreatedElems.Append(presentBndElems[i]); } + } // loop on given elements - // 4. Fill group with missing boundary elements + // --------------------------------------------- + // 4. Fill group with boundary elements + // --------------------------------------------- if ( group ) { if ( SMESHDS_Group* g = dynamic_cast( group->GetGroupDS() )) @@ -10269,9 +11773,12 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, g->SMDSGroup().Add( tgtEditor.myLastCreatedElems( i+1 )); } tgtEditor.myLastCreatedElems.Clear(); + tgtEditor2.myLastCreatedElems.Clear(); + // ----------------------- // 5. Copy given elements - if ( toCopyElements ) + // ----------------------- + if ( toCopyElements && targetMesh != myMesh ) { if (elements.empty()) eIt = aMesh->elementsIterator(elemType); @@ -10288,5 +11795,5 @@ void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, tgtEditor.myLastCreatedElems.Clear(); } } - return; + return nbAddedBnd; }