From ed0ea97e94b5f01f69fac650fd655959620c1bb8 Mon Sep 17 00:00:00 2001 From: jfa Date: Sat, 5 Mar 2005 11:30:59 +0000 Subject: [PATCH] Pattern mapping: replace adjacent faces with polygons to obtain conform mesh. Improve polygons and polyhedral volumes processing. --- idl/SMESH_Pattern.idl | 7 +- src/SMDS/SMDS_Mesh.cxx | 50 ++++++++- src/SMDS/SMDS_Mesh.hxx | 4 + src/SMESH/SMESH_MeshEditor.cxx | 113 ++++++++++++++++++++- src/SMESH/SMESH_Pattern.cxx | 45 +++++++- src/SMESH/SMESH_Pattern.hxx | 4 +- src/SMESHGUI/SMESHGUI_CreatePatternDlg.cxx | 21 ---- src/SMESHGUI/SMESHGUI_CreatePatternDlg.h | 17 ---- src/SMESHGUI/SMESHGUI_MeshPatternDlg.cxx | 10 +- src/SMESHGUI/SMESHGUI_MeshPatternDlg.h | 18 +--- src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx | 11 +- src/SMESH_I/SMESH_Pattern_i.cxx | 5 +- src/SMESH_I/SMESH_Pattern_i.hxx | 3 +- 13 files changed, 235 insertions(+), 73 deletions(-) diff --git a/idl/SMESH_Pattern.idl b/idl/SMESH_Pattern.idl index fa1d7dd11..bf65b38e6 100644 --- a/idl/SMESH_Pattern.idl +++ b/idl/SMESH_Pattern.idl @@ -103,9 +103,12 @@ module SMESH /*! * Create nodes and elements in using nodes - * coordinates computed by either of Apply...() methods + * coordinates computed by either of Apply...() methods. + * If CreatePoly is TRUE, replace adjacent faces by polygons, + * inserting new nodes in common links. */ - boolean MakeMesh(in SMESH_Mesh theMesh); + boolean MakeMesh (in SMESH_Mesh theMesh, + in boolean CreatePoly); /*! * Return the loaded pattern in the string form to be saved in file diff --git a/src/SMDS/SMDS_Mesh.cxx b/src/SMDS/SMDS_Mesh.cxx index e6751c3f0..1da783697 100644 --- a/src/SMDS/SMDS_Mesh.cxx +++ b/src/SMDS/SMDS_Mesh.cxx @@ -1385,6 +1385,55 @@ const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const return myElementIDFactory->MeshElement(IDelem); } +//======================================================================= +//function : FindFace +//purpose : find polygon +//======================================================================= + +const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector nodes_ids) const +{ + int nbnodes = nodes_ids.size(); + std::vector poly_nodes (nbnodes); + for (int inode = 0; inode < nbnodes; inode++) { + const SMDS_MeshNode * node = FindNode(nodes_ids[inode]); + if (node == NULL) return NULL; + } + return FindFace(poly_nodes); +} + +const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector nodes) +{ + int nbNodes = nodes.size(); + if (nbNodes < 1) return NULL; + + bool isFound = true; + const SMDS_MeshFace * face; + set faces; + + for (int inode = 0; inode < nbNodes && isFound; inode++) { + set new_faces; + + SMDS_ElemIteratorPtr itF = nodes[inode]->facesIterator(); + while (itF->more()) { + face = static_cast(itF->next()); + if (face->NbNodes() == nbNodes) { + if (inode == 0 || faces.find(face) != faces.end()) { + new_faces.insert(face); + } + } + } + faces = new_faces; + if (new_faces.size() == 0) { + isFound = false; + } + } + + if (isFound) + return face; + + return NULL; +} + //======================================================================= //function : DumpNodes //purpose : @@ -2129,4 +2178,3 @@ void SMDS_Mesh::Renumber (const bool isNodes, const int startID, const int del ID += deltaID; } } - diff --git a/src/SMDS/SMDS_Mesh.hxx b/src/SMDS/SMDS_Mesh.hxx index 6f693dc57..9d59a3ddf 100644 --- a/src/SMDS/SMDS_Mesh.hxx +++ b/src/SMDS/SMDS_Mesh.hxx @@ -260,6 +260,10 @@ public: const SMDS_MeshNode *n2, const SMDS_MeshNode *n3, const SMDS_MeshNode *n4); + + const SMDS_MeshFace *FindFace(std::vector nodes_ids) const; + static const SMDS_MeshFace* FindFace(std::vector nodes); + int MaxNodeID() const; int MinNodeID() const; int MaxElementID() const; diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 1fdb16b71..40aabbe55 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -1274,6 +1274,8 @@ void laplacianSmooth(SMESHDS_Mesh * theMesh, if ( theElems.find( elem ) == theElems.end() ) continue; + if (elem->IsPoly()) + continue; int i = 0, iNode = 0; const SMDS_MeshNode* aNodes [4]; SMDS_ElemIteratorPtr itN = elem->nodesIterator(); @@ -1858,7 +1860,8 @@ static void makeWalls (SMESHDS_Mesh* aMesh, for (int inode = 0; inode < nbPolygonNodes; inode++) { polygon_nodes[inode] = nodes[inode]; } - aMesh->AddPolygonalFace(polygon_nodes); + if (!hasFreeLinks || !aMesh->FindFace(polygon_nodes)) + aMesh->AddPolygonalFace(polygon_nodes); } break; } @@ -2691,6 +2694,92 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) int nbUniqueNodes = nodeSet.size(); if ( nbNodes != nbUniqueNodes ) // some nodes stick { + // Polygons and Polyhedral volumes + if (elem->IsPoly()) { + + if (elem->GetType() == SMDSAbs_Face) { + // Polygon + if (nbUniqueNodes < 3) { + isOk = false; + } else { + // get simple seq of nodes + const SMDS_MeshNode* simpleNodes[ nbNodes ]; + int iSimple = 0; + + simpleNodes[iSimple++] = curNodes[0]; + for (iCur = 1; iCur < nbNodes; iCur++) { + if (curNodes[iCur] != simpleNodes[iSimple - 1]) { + simpleNodes[iSimple++] = curNodes[iCur]; + } + } + int nbSimple = iSimple; + if (simpleNodes[nbSimple - 1] == simpleNodes[0]) { + nbSimple--; + } + + // separate cycles + bool foundCycle = (nbSimple > nbUniqueNodes); + while (foundCycle) { + foundCycle = false; + set cycleSet; + for (iSimple = 0; iSimple < nbSimple && !foundCycle; iSimple++) { + const SMDS_MeshNode* n = simpleNodes[iSimple]; + if (!cycleSet.insert( n ).second) { + foundCycle = true; + + // separate cycle + int iC = 0, curLast = iSimple; + for (; iC < curLast; iC++) { + if (simpleNodes[iC] == n) break; + } + int cycleLen = curLast - iC; + if (cycleLen > 2) { + // create sub-element + vector poly_nodes (cycleLen); + for (int ii = 0; iC < curLast; iC++) { + poly_nodes[ii++] = simpleNodes[iC]; + } + SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes); + if (aShapeId) + aMesh->SetMeshElementOnShape(newElem, aShapeId); + } + // put the rest nodes from the first cycle position + for (iC = curLast + 1; iC < nbSimple; iC++) { + simpleNodes[iC - cycleLen] = simpleNodes[iC]; + } + nbSimple -= cycleLen; + } + } // for (iSimple = 0; iSimple < nbSimple; iSimple++) + } // while (foundCycle) + + if (iSimple > 2) { + aMesh->ChangeElementNodes(elem, simpleNodes, nbSimple); + } else { + isOk = false; + } + } + + } else if (elem->GetType() == SMDSAbs_Volume) { + // Polyhedral volume + if (nbUniqueNodes < 4) { + isOk = false; + } else { + // each face has to be analized in order to check volume validity + //aMesh->ChangeElementNodes(elem, uniqueNodes, nbUniqueNodes); + isOk = false; + } + + } else { + isOk = false; + } + + if (!isOk) + rmElemIds.push_back(elem->GetID()); + + continue; + } + + // Regular elements switch ( nbNodes ) { case 2: ///////////////////////////////////// EDGE isOk = false; break; @@ -3930,17 +4019,31 @@ SMESH_MeshEditor::Sew_Error bool isNewFace = setOfFaceNodeSet.insert( faceNodeSet ).second; if ( isNewFace ) { // no such a face is given but it still can exist, check it - if ( nbNodes == 3 ) + if ( nbNodes == 3 ) { aFreeFace = aMesh->FindFace( fNodes[0],fNodes[1],fNodes[2] ); - else + } else if ( nbNodes == 4 ) { aFreeFace = aMesh->FindFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] ); + } else { + vector poly_nodes (nbNodes); + for (int inode = 0; inode < nbNodes; inode++) { + poly_nodes[inode] = fNodes[inode]; + } + aFreeFace = aMesh->FindFace(poly_nodes); + } } if ( !aFreeFace ) { // create a temporary face - if ( nbNodes == 3 ) + if ( nbNodes == 3 ) { aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2] ); - else + } else if ( nbNodes == 4 ) { aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] ); + } else { + vector poly_nodes (nbNodes); + for (int inode = 0; inode < nbNodes; inode++) { + poly_nodes[inode] = fNodes[inode]; + } + aFreeFace = aTmpFacesMesh.AddPolygonalFace(poly_nodes); + } } if ( aFreeFace ) freeFaceList.push_back( aFreeFace ); diff --git a/src/SMESH/SMESH_Pattern.cxx b/src/SMESH/SMESH_Pattern.cxx index 0aeffec35..55c37130c 100644 --- a/src/SMESH/SMESH_Pattern.cxx +++ b/src/SMESH/SMESH_Pattern.cxx @@ -2681,6 +2681,9 @@ void SMESH_Pattern::mergePoints (map > >& indGroups, } } } + + // save links to update adjacent faces in MakeMesh() method + myLinks = indGroups; } //======================================================================= @@ -3135,7 +3138,7 @@ bool SMESH_Pattern::Apply (const SMDS_MeshVolume* theVolume, // coordinates computed by either of Apply...() methods //======================================================================= -bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh) +bool SMESH_Pattern::MakeMesh (SMESH_Mesh* theMesh, bool toCreatePoly) { MESSAGE(" ::MakeMesh() " ); if ( !myIsComputed ) @@ -3368,6 +3371,46 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh) editor.Remove( elemIDs, false ); } + if (toCreatePoly && myIs2D) { + // replace adjacent faces by polygons, inserting nodes in common link + + map< TNodeSet, list< list > >::iterator linksIt; + for (linksIt = myLinks.begin(); linksIt != myLinks.end(); linksIt++) { + // end nodes of link + set ends = linksIt->first; + set::iterator endsIt = ends.begin(); + const SMDS_MeshNode* n1 = *endsIt; + endsIt++; + const SMDS_MeshNode* n2 = *endsIt; + + // middle nodes of link (to be inserted in adjacent faces) + list link_nodes; + + list< list > coincident_links = linksIt->second; + list& link = coincident_links.front(); + list::iterator linkIt = link.begin(); + for (; linkIt != link.end(); linkIt++) { + if (onMeshElements) + link_nodes.push_back(nodesVector[ *linkIt ]); + else + link_nodes.push_back(pointNodeMap[ & myPoints[ *linkIt ]]); + } + + // update all adjacent faces + set elemSet, avoidSet; + while (true) { + const SMDS_MeshElement* adjElem = + SMESH_MeshEditor::FindFaceInSet(n1, n2, elemSet, avoidSet); + if (adjElem) { + SMESH_MeshEditor editor (theMesh); + editor.InsertNodesIntoLink(adjElem, n1, n2, link_nodes, toCreatePoly); + } else { + break; + } + } + } + } + return setErrorCode( ERR_OK ); } diff --git a/src/SMESH/SMESH_Pattern.hxx b/src/SMESH/SMESH_Pattern.hxx index 670578ce4..baa9361b8 100644 --- a/src/SMESH/SMESH_Pattern.hxx +++ b/src/SMESH/SMESH_Pattern.hxx @@ -128,7 +128,7 @@ class SMESH_Pattern { bool GetMappedPoints ( std::list & thePoints ) const; // Return nodes coordinates computed by Apply() method - bool MakeMesh(SMESH_Mesh* theMesh); + bool MakeMesh (SMESH_Mesh* theMesh, bool toCreatePoly = false); // Create nodes and elements in using nodes // coordinates computed by either of Apply...() methods @@ -306,6 +306,8 @@ class SMESH_Pattern { std::map< int, const SMDS_MeshNode*> myXYZIdToNodeMap; // map id to node of a refined element std::vector myElements; // refined elements std::vector myOrderedNodes; + + std::map< TNodeSet, std::list< std::list > > myLinks; }; diff --git a/src/SMESHGUI/SMESHGUI_CreatePatternDlg.cxx b/src/SMESHGUI/SMESHGUI_CreatePatternDlg.cxx index fd903bbc6..4c8dce337 100755 --- a/src/SMESHGUI/SMESHGUI_CreatePatternDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_CreatePatternDlg.cxx @@ -774,24 +774,3 @@ void SMESHGUI_CreatePatternDlg::onTypeChanged( int theType ) else myPicture2d->hide(); } - - - - - - - - - - - - - - - - - - - - - diff --git a/src/SMESHGUI/SMESHGUI_CreatePatternDlg.h b/src/SMESHGUI/SMESHGUI_CreatePatternDlg.h index 40fbfe1b7..be75abe5a 100755 --- a/src/SMESHGUI/SMESHGUI_CreatePatternDlg.h +++ b/src/SMESHGUI/SMESHGUI_CreatePatternDlg.h @@ -139,20 +139,3 @@ private: }; #endif - - - - - - - - - - - - - - - - - diff --git a/src/SMESHGUI/SMESHGUI_MeshPatternDlg.cxx b/src/SMESHGUI/SMESHGUI_MeshPatternDlg.cxx index efc4eec75..657020393 100755 --- a/src/SMESHGUI/SMESHGUI_MeshPatternDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_MeshPatternDlg.cxx @@ -206,6 +206,9 @@ QFrame* SMESHGUI_MeshPatternDlg::createMainFrame( QWidget* theParent ) // reverse check box myReverseChk = new QCheckBox( tr( "REVERSE" ), aPatGrp ); + // CreatePoly check box + myCreatePolyChk = new QCheckBox( tr( "CREATE_POLYGONS_NEAR_BOUNDARY" ), aPatGrp ); + // Pictures 2d and 3d for ( int i = 0; i < 2; i++ ) { @@ -389,7 +392,9 @@ bool SMESHGUI_MeshPatternDlg::onApply() myGeomObj[ Object ], myGeomObj[ Vertex1 ], myGeomObj[ Vertex2 ] ); } - if ( myPattern->MakeMesh( myMesh ) ) + bool toCreatePoly = (myCreatePolyChk->isChecked() && (myType == Type_2d)); + + if ( myPattern->MakeMesh( myMesh, toCreatePoly ) ) { mySelection->ClearIObjects(); SMESHGUI* aCompGUI = SMESHGUI::GetSMESHGUI(); @@ -1121,6 +1126,7 @@ void SMESHGUI_MeshPatternDlg::onTypeChanged( int theType ) mySelBtn [ Vertex2 ]->hide(); mySelEdit[ Vertex2 ]->hide(); myReverseChk->show(); + myCreatePolyChk->show(); myPicture2d->show(); myPicture3d->hide(); mySelLbl[ Object ]->setText( tr( "FACE" ) ); @@ -1137,6 +1143,7 @@ void SMESHGUI_MeshPatternDlg::onTypeChanged( int theType ) mySelBtn [ Vertex2 ]->show(); mySelEdit[ Vertex2 ]->show(); myReverseChk->hide(); + myCreatePolyChk->hide(); myPicture2d->hide(); myPicture3d->show(); mySelLbl[ Object ]->setText( tr( "3D_BLOCK" ) ); @@ -1386,4 +1393,3 @@ int SMESHGUI_MeshPatternDlg::getNode( bool second ) const { return second ? myNode2->value() - 1 : myNode1->value() - 1; } - diff --git a/src/SMESHGUI/SMESHGUI_MeshPatternDlg.h b/src/SMESHGUI/SMESHGUI_MeshPatternDlg.h index 26a733236..4a780322b 100755 --- a/src/SMESHGUI/SMESHGUI_MeshPatternDlg.h +++ b/src/SMESHGUI/SMESHGUI_MeshPatternDlg.h @@ -145,6 +145,7 @@ private: QPushButton* myNewBtn; QCheckBox* myReverseChk; + QCheckBox* myCreatePolyChk; SMESHGUI_PatternWidget* myPicture2d; QFrame* myPicture3d; QLabel* myPreview3d; @@ -168,20 +169,3 @@ private: }; #endif - - - - - - - - - - - - - - - - - diff --git a/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx b/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx index d311b490e..e2ee202b3 100755 --- a/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include #include #include @@ -332,12 +334,15 @@ SMESH::long_array_var SMESHGUI_MultiEditDlg::getIds() { vtkTriangle* aTri = vtkTriangle::SafeDownCast(aCell); vtkQuad* aQua = vtkQuad::SafeDownCast(aCell); - vtkCell3D* a3d = vtkCell3D::SafeDownCast(aCell); + vtkPolygon* aPG = vtkPolygon::SafeDownCast(aCell); + + vtkCell3D* a3d = vtkCell3D::SafeDownCast(aCell); + vtkConvexPointSet* aPH = vtkConvexPointSet::SafeDownCast(aCell); if ( aTri && myFilterType == SMESHGUI_TriaFilter || aQua && myFilterType == SMESHGUI_QuadFilter || - ( aTri || aQua ) && myFilterType == SMESHGUI_FaceFilter || - a3d && myFilterType == SMESHGUI_VolumeFilter ) + ( aTri || aQua || aPG ) && myFilterType == SMESHGUI_FaceFilter || + ( a3d || aPH ) && myFilterType == SMESHGUI_VolumeFilter ) { int anObjId = aVisualObj->GetElemObjId( i ); myIds.Add( anObjId ); diff --git a/src/SMESH_I/SMESH_Pattern_i.cxx b/src/SMESH_I/SMESH_Pattern_i.cxx index d0b8bd216..107a26eca 100644 --- a/src/SMESH_I/SMESH_Pattern_i.cxx +++ b/src/SMESH_I/SMESH_Pattern_i.cxx @@ -296,13 +296,14 @@ SMESH::point_array* //purpose : //======================================================================= -CORBA::Boolean SMESH_Pattern_i::MakeMesh(SMESH::SMESH_Mesh_ptr theMesh) +CORBA::Boolean SMESH_Pattern_i::MakeMesh (SMESH::SMESH_Mesh_ptr theMesh, + const CORBA::Boolean CreatePoly) { ::SMESH_Mesh* aMesh = getMesh( theMesh ); if ( !aMesh ) return false; - return myPattern.MakeMesh( aMesh ); + return myPattern.MakeMesh( aMesh, CreatePoly ); } //======================================================================= diff --git a/src/SMESH_I/SMESH_Pattern_i.hxx b/src/SMESH_I/SMESH_Pattern_i.hxx index d0a9656bd..1a3428fcc 100644 --- a/src/SMESH_I/SMESH_Pattern_i.hxx +++ b/src/SMESH_I/SMESH_Pattern_i.hxx @@ -75,7 +75,8 @@ class SMESH_Pattern_i: CORBA::Long theNode000Index, CORBA::Long theNode001Index); - CORBA::Boolean MakeMesh(SMESH::SMESH_Mesh_ptr theMesh); + CORBA::Boolean MakeMesh (SMESH::SMESH_Mesh_ptr theMesh, + const CORBA::Boolean CreatePoly); SMESH::SMESH_Pattern::ErrorCode GetErrorCode(); -- 2.39.2