Salome HOME
Pattern mapping: replace adjacent faces with polygons to obtain conform mesh. Improve...
authorjfa <jfa@opencascade.com>
Sat, 5 Mar 2005 11:30:59 +0000 (11:30 +0000)
committerjfa <jfa@opencascade.com>
Sat, 5 Mar 2005 11:30:59 +0000 (11:30 +0000)
13 files changed:
idl/SMESH_Pattern.idl
src/SMDS/SMDS_Mesh.cxx
src/SMDS/SMDS_Mesh.hxx
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_Pattern.cxx
src/SMESH/SMESH_Pattern.hxx
src/SMESHGUI/SMESHGUI_CreatePatternDlg.cxx
src/SMESHGUI/SMESHGUI_CreatePatternDlg.h
src/SMESHGUI/SMESHGUI_MeshPatternDlg.cxx
src/SMESHGUI/SMESHGUI_MeshPatternDlg.h
src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx
src/SMESH_I/SMESH_Pattern_i.cxx
src/SMESH_I/SMESH_Pattern_i.hxx

index fa1d7dd119bba1b3159e12e7eb15d19664af21d3..bf65b38e61988976371f15a10cfcc7d81f75dc85 100644 (file)
@@ -103,9 +103,12 @@ module SMESH
 
     /*!
      * Create nodes and elements in <theMesh> 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
index e6751c3f03a1bd8cec899cde21311b2f7d7ddb67..1da78369748752172df1a975880355d82ea1f3bf 100644 (file)
@@ -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<int> nodes_ids) const
+{
+  int nbnodes = nodes_ids.size();
+  std::vector<const SMDS_MeshNode *> 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<const SMDS_MeshNode *> nodes)
+{
+  int nbNodes = nodes.size();
+  if (nbNodes < 1) return NULL;
+
+  bool isFound = true;
+  const SMDS_MeshFace * face;
+  set<const SMDS_MeshFace *> faces;
+
+  for (int inode = 0; inode < nbNodes && isFound; inode++) {
+    set<const SMDS_MeshFace *> new_faces;
+
+    SMDS_ElemIteratorPtr itF = nodes[inode]->facesIterator();
+    while (itF->more()) {
+      face = static_cast<const SMDS_MeshFace *>(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;
   }
 }
-
index 6f693dc57a05b8d4e272fac0a3cbd28532d1e029..9d59a3ddff3c0360510ef3651b5504dfd847e34d 100644 (file)
@@ -260,6 +260,10 @@ public:
                                        const SMDS_MeshNode *n2,
                                        const SMDS_MeshNode *n3,
                                        const SMDS_MeshNode *n4);
+
+  const SMDS_MeshFace *FindFace(std::vector<int> nodes_ids) const;
+  static const SMDS_MeshFace* FindFace(std::vector<const SMDS_MeshNode *> nodes);
+
   int MaxNodeID() const;
   int MinNodeID() const;
   int MaxElementID() const;
index 1fdb16b7190d0a514b3bac57ab88f1854be33647..40aabbe557b7fab20d3729eefc60621458e7f86d 100644 (file)
@@ -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<const SMDS_MeshNode*> 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<const SMDS_MeshNode *> 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<const SMDS_MeshNode *> 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<const SMDS_MeshNode *> 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 );
index 0aeffec35e495ac8023ea97466360befeea2adcd..55c37130c816e7ba596371379e146681848793cc 100644 (file)
@@ -2681,6 +2681,9 @@ void SMESH_Pattern::mergePoints (map<TNodeSet, list<list<int> > >&  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<int> > >::iterator linksIt;
+    for (linksIt = myLinks.begin(); linksIt != myLinks.end(); linksIt++) {
+      // end nodes of link
+      set<const SMDS_MeshNode*> ends = linksIt->first;
+      set<const SMDS_MeshNode*>::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<const SMDS_MeshNode*> link_nodes;
+
+      list< list<int> > coincident_links = linksIt->second;
+      list<int>& link = coincident_links.front();
+      list<int>::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<const SMDS_MeshElement*> 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 );
 }
 
index 670578ce459d1e04bfb6eab8028309fb57c9d848..baa9361b829880fc3397847e5954a4aa2eb6d1fe 100644 (file)
@@ -128,7 +128,7 @@ class SMESH_Pattern {
   bool GetMappedPoints ( std::list<const gp_XYZ *> & 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 <theMesh> 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<const SMDS_MeshElement*> myElements; // refined elements
   std::vector<const SMDS_MeshNode*> myOrderedNodes;
+
+  std::map< TNodeSet, std::list< std::list<int> > > myLinks;
 };
 
 
index fd903bbc62b8126813ed9a5d6388b611176b0402..4c8dce337e842fd7cb55e6b9359317f3993df5b2 100755 (executable)
@@ -774,24 +774,3 @@ void SMESHGUI_CreatePatternDlg::onTypeChanged( int theType )
   else\r
     myPicture2d->hide();\r
 }\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
index 40fbfe1b749bd74b262452e97ecc546a66f1a887..be75abe5a4b1180c6a84f42e490dbc8d6b594c76 100755 (executable)
@@ -139,20 +139,3 @@ private:
 };\r
 \r
 #endif\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
index efc4eec75b498820220a6801e343c5db478b77da..6570203935b208a011fc0e45b11dc9b64b3e7911 100755 (executable)
@@ -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;
 }
-
index 26a7332365a116fdc5570cd1975e04a196275412..4a780322b30cb463036ff3d3b0d9f1b4713e1270 100755 (executable)
@@ -145,6 +145,7 @@ private:
   QPushButton*                        myNewBtn;
 
   QCheckBox*                          myReverseChk;
+  QCheckBox*                          myCreatePolyChk;
   SMESHGUI_PatternWidget*             myPicture2d;
   QFrame*                             myPicture3d;
   QLabel*                             myPreview3d;
@@ -168,20 +169,3 @@ private:
 };
 
 #endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
index d311b490e3900dfd661fbdb8dbd5d9c9d65c6145..e2ee202b32cc97ba6b8cd13f867b1a50165bd62f 100755 (executable)
@@ -50,6 +50,8 @@
 #include <vtkCell3D.h>
 #include <vtkQuad.h>
 #include <vtkTriangle.h>
+#include <vtkPolygon.h>
+#include <vtkConvexPointSet.h>
 #include <vtkIdList.h>
 #include <vtkIntArray.h>
 #include <vtkCellArray.h>
@@ -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 );
index d0b8bd2161188c900139d0b9ce6a5fee5d7a2963..107a26eca992e4a0c09275bec2d5e34e16c58b79 100644 (file)
@@ -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 );
 }
 
 //=======================================================================
index d0a9656bd288b4de626bdee1a261c0b49b7e0cfd..1a3428fccd039e025ed8e7fe00ef22e7e44f4fee 100644 (file)
@@ -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();