Salome HOME
smds_memimp_joints
authorprascle <prascle>
Sun, 25 Jul 2010 08:13:16 +0000 (08:13 +0000)
committerprascle <prascle>
Sun, 25 Jul 2010 08:13:16 +0000 (08:13 +0000)
25 files changed:
idl/SMESH_MeshEditor.idl
src/SMDS/SMDS_Downward.cxx
src/SMDS/SMDS_Downward.hxx
src/SMDS/SMDS_FaceOfEdges.hxx
src/SMDS/SMDS_LinearEdge.hxx
src/SMDS/SMDS_Mesh.cxx
src/SMDS/SMDS_Mesh.hxx
src/SMDS/SMDS_Mesh0DElement.hxx
src/SMDS/SMDS_MeshCell.hxx
src/SMDS/SMDS_MeshIDFactory.cxx
src/SMDS/SMDS_MeshIDFactory.hxx
src/SMDS/SMDS_UnstructuredGrid.cxx
src/SMDS/SMDS_UnstructuredGrid.hxx
src/SMDS/SMDS_VolumeOfFaces.hxx
src/SMDS/SMDS_VtkEdge.cxx
src/SMDS/SMDS_VtkEdge.hxx
src/SMDS/SMDS_VtkFace.cxx
src/SMDS/SMDS_VtkVolume.cxx
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MeshEditor.hxx
src/SMESHDS/SMESHDS_Mesh.cxx
src/SMESHDS/SMESHDS_Mesh.hxx
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.hxx
src/SMESH_SWIG/smeshDC.py

index 983b2f4865e36448eeb5b3546ed76dbe88b257ee..5e8c8c5f373c16c6a379f29eecf339d0854fb29b 100644 (file)
@@ -869,6 +869,19 @@ module SMESH
      */
     boolean Make2DMeshFrom3D();
 
+    /*!
+     * \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.
+     * \param theDomains - list of groups of volumes
+     * \param createJointElems - if TRUE, create the elements
+     * \return TRUE if operation has been completed successfully, FALSE otherwise
+     */
+    boolean DoubleNodesOnGroupBoundaries( in ListOfGroups theDomains,
+                                          in boolean createJointElems );
+
   };
 };
 
index f3fbd0efcd6ced7b9bb5292b8a01e27f23867b84..6875aebd5bf5e3404cb75c8bfa1287d7b6aeea08 100644 (file)
@@ -265,6 +265,12 @@ const unsigned char* SMDS_Down1D::getUpTypes(int cellId)
   return &_upCellTypes[_upCellIndex[cellId]];
 }
 
+void SMDS_Down1D::getNodeIds(int cellId, std::set<int>& nodeSet)
+{
+  for (int i = 0; i < _nbDownCells; i++)
+    nodeSet.insert(_cellIds[_nbDownCells * cellId + i]);
+}
+
 int SMDS_Down1D::getNodeSet(int cellId, int* nodeSet)
 {
   for (int i = 0; i < _nbDownCells; i++)
@@ -481,6 +487,16 @@ const unsigned char* SMDS_Down2D::getUpTypes(int cellId)
   return &_upCellTypes[2 * cellId];
 }
 
+void SMDS_Down2D::getNodeIds(int cellId, std::set<int>& nodeSet)
+{
+  for (int i = 0; i < _nbDownCells; i++)
+    {
+      int downCellId = _cellIds[_nbDownCells * cellId + i];
+      unsigned char cellType = _cellTypes[i];
+      this->_grid->getDownArray(cellType)->getNodeIds(downCellId, nodeSet);
+    }
+}
+
 /*! Find in vtkUnstructuredGrid the volumes containing a face already stored in vtkUnstructuredGrid.
  * Search the volumes containing a face, to store the info in SMDS_Down2D for later uses
  * with SMDS_Down2D::getUpCells and SMDS_Down2D::getUpTypes.
@@ -753,6 +769,16 @@ const unsigned char* SMDS_Down3D::getUpTypes(int cellId)
   return 0;
 }
 
+void SMDS_Down3D::getNodeIds(int cellId, std::set<int>& nodeSet)
+{
+  int vtkId = this->_vtkCellIds[cellId];
+  vtkIdType npts = 0;
+  vtkIdType *nodes; // will refer to the point id's of the volume
+  _grid->GetCellPoints(vtkId, npts, nodes);
+  for (int i = 0; i < npts; i++)
+    nodeSet.insert(nodes[i]);
+}
+
 int SMDS_Down3D::FindFaceByNodes(int cellId, ElemByNodesType& faceByNodes)
 {
   int *faces = &_cellIds[_nbDownCells * cellId];
@@ -1074,6 +1100,37 @@ SMDS_DownTetra::~SMDS_DownTetra()
 {
 }
 
+void SMDS_DownTetra::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
+{
+  set<int> setNodes;
+  setNodes.clear();
+  for (int i = 0; i < orderedNodes.size(); i++)
+    setNodes.insert(orderedNodes[i]);
+  //MESSAGE("cellId = " << cellId);
+
+  vtkIdType npts = 0;
+  vtkIdType *nodes; // will refer to the point id's of the volume
+  _grid->GetCellPoints(this->_vtkCellIds[cellId], npts, nodes);
+
+  set<int> tofind;
+  int ids[12] = { 0, 1, 2, 0, 1, 3, 0, 2, 3, 1, 2, 3 };
+  for (int k = 0; k < 4; k++)
+    {
+      tofind.clear();
+      for (int i = 0; i < 3; i++)
+        tofind.insert(nodes[ids[3 * k + i]]);
+      if (setNodes == tofind)
+        {
+          for (int i = 0; i < 3; i++)
+            orderedNodes[i] = nodes[ids[3 * k + i]];
+          return;
+        }
+    }
+  MESSAGE("=== Problem volume " << _vtkCellIds[cellId] << " " << _grid->_mesh->fromVtkToSmds(_vtkCellIds[cellId]));
+  MESSAGE(orderedNodes[0] << " " << orderedNodes[1] << " " << orderedNodes[2]);
+  MESSAGE(nodes[0] << " " << nodes[1] << " " << nodes[2] << " " << nodes[3]);
+}
+
 void SMDS_DownTetra::addDownCell(int cellId, int lowCellId, unsigned char aType)
 {
   //ASSERT((cellId >=0)&& (cellId < _maxId));
@@ -1150,6 +1207,11 @@ SMDS_DownQuadTetra::~SMDS_DownQuadTetra()
 {
 }
 
+void SMDS_DownQuadTetra::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
+{
+  // TODO
+}
+
 void SMDS_DownQuadTetra::addDownCell(int cellId, int lowCellId, unsigned char aType)
 {
   //ASSERT((cellId >=0)&& (cellId < _maxId));
@@ -1241,6 +1303,11 @@ SMDS_DownPyramid::~SMDS_DownPyramid()
 {
 }
 
+void SMDS_DownPyramid::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
+{
+  // TODO
+}
+
 void SMDS_DownPyramid::addDownCell(int cellId, int lowCellId, unsigned char aType)
 {
   //ASSERT((cellId >=0) && (cellId < _maxId));
@@ -1340,6 +1407,11 @@ SMDS_DownQuadPyramid::~SMDS_DownQuadPyramid()
 {
 }
 
+void SMDS_DownQuadPyramid::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
+{
+  // TODO
+}
+
 void SMDS_DownQuadPyramid::addDownCell(int cellId, int lowCellId, unsigned char aType)
 {
   //ASSERT((cellId >=0) && (cellId < _maxId));
@@ -1456,6 +1528,11 @@ SMDS_DownPenta::~SMDS_DownPenta()
 {
 }
 
+void SMDS_DownPenta::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
+{
+  // TODO
+}
+
 void SMDS_DownPenta::addDownCell(int cellId, int lowCellId, unsigned char aType)
 {
   //ASSERT((cellId >=0) && (cellId < _maxId));
@@ -1559,6 +1636,11 @@ SMDS_DownQuadPenta::~SMDS_DownQuadPenta()
 {
 }
 
+void SMDS_DownQuadPenta::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
+{
+  // TODO
+}
+
 void SMDS_DownQuadPenta::addDownCell(int cellId, int lowCellId, unsigned char aType)
 {
   //ASSERT((cellId >=0) && (cellId < _maxId));
@@ -1682,6 +1764,11 @@ SMDS_DownHexa::~SMDS_DownHexa()
 {
 }
 
+void SMDS_DownHexa::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
+{
+  // TODO
+}
+
 void SMDS_DownHexa::addDownCell(int cellId, int lowCellId, unsigned char aType)
 {
   //ASSERT((cellId >=0)&& (cellId < _maxId));
@@ -1780,6 +1867,11 @@ SMDS_DownQuadHexa::~SMDS_DownQuadHexa()
 {
 }
 
+void SMDS_DownQuadHexa::getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes)
+{
+  // TODO
+}
+
 void SMDS_DownQuadHexa::addDownCell(int cellId, int lowCellId, unsigned char aType)
 {
   //ASSERT((cellId >=0)&& (cellId < _maxId));
index fd4eca020b4459ffe0f7d7c9fc2faae5b5573a0a..d9b12a05470ae671f99b043f66c38b027a735ae6 100644 (file)
@@ -26,6 +26,28 @@ typedef struct
   int nbElems;
 } ListElemByNodesType; // TODO resize for polyhedrons
 
+class DownIdType
+{
+public:
+  DownIdType(int a, unsigned char b) :
+    cellId(a), cellType(b)
+  {
+  }
+  int cellId;
+  unsigned char cellType;
+};
+
+struct DownIdCompare
+{
+  bool operator ()(const DownIdType e1, const DownIdType e2) const
+  {
+    if (e1.cellId == e2.cellId)
+      return (e1.cellType < e2.cellType);
+    else
+      return (e1.cellId < e2.cellId);
+  }
+};
+
 class SMDS_Downward
 {
   friend class SMDS_UnstructuredGrid;
@@ -38,6 +60,7 @@ public:
   virtual int getNumberOfUpCells(int cellId) = 0;
   virtual const int* getUpCells(int cellId) = 0;
   virtual const unsigned char* getUpTypes(int cellId) = 0;
+  virtual void getNodeIds(int cellId, std::set<int>& nodeSet) = 0;
   int getVtkCellId(int cellId)
   {
     return _vtkCellIds[cellId];
@@ -75,6 +98,7 @@ public:
   virtual int getNumberOfUpCells(int cellId);
   virtual const int* getUpCells(int cellId);
   virtual const unsigned char* getUpTypes(int cellId);
+  virtual void getNodeIds(int cellId, std::set<int>& nodeSet);
 protected:
   SMDS_Down1D(SMDS_UnstructuredGrid *grid, int nbDownCells);
   ~SMDS_Down1D();
@@ -105,6 +129,7 @@ public:
   virtual int getNumberOfUpCells(int cellId);
   virtual const int* getUpCells(int cellId);
   virtual const unsigned char* getUpTypes(int cellId);
+  virtual void getNodeIds(int cellId, std::set<int>& nodeSet);
 protected:
   SMDS_Down2D(SMDS_UnstructuredGrid *grid, int nbDownCells);
   ~SMDS_Down2D();
@@ -134,6 +159,8 @@ public:
   virtual int getNumberOfUpCells(int cellId);
   virtual const int* getUpCells(int cellId);
   virtual const unsigned char* getUpTypes(int cellId);
+  virtual void getNodeIds(int cellId, std::set<int>& nodeSet);
+  virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes) = 0;
 protected:
   SMDS_Down3D(SMDS_UnstructuredGrid *grid, int nbDownCells);
   ~SMDS_Down3D();
@@ -225,6 +252,7 @@ class SMDS_DownTetra: public SMDS_Down3D
 {
   friend class SMDS_UnstructuredGrid;
 public:
+  virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
 protected:
   SMDS_DownTetra(SMDS_UnstructuredGrid *grid);
   ~SMDS_DownTetra();
@@ -236,6 +264,7 @@ class SMDS_DownQuadTetra: public SMDS_Down3D
 {
   friend class SMDS_UnstructuredGrid;
 public:
+  virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
 protected:
   SMDS_DownQuadTetra(SMDS_UnstructuredGrid *grid);
   ~SMDS_DownQuadTetra();
@@ -247,6 +276,7 @@ class SMDS_DownPyramid: public SMDS_Down3D
 {
   friend class SMDS_UnstructuredGrid;
 public:
+  virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
 protected:
   SMDS_DownPyramid(SMDS_UnstructuredGrid *grid);
   ~SMDS_DownPyramid();
@@ -258,6 +288,7 @@ class SMDS_DownQuadPyramid: public SMDS_Down3D
 {
   friend class SMDS_UnstructuredGrid;
 public:
+  virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
 protected:
   SMDS_DownQuadPyramid(SMDS_UnstructuredGrid *grid);
   ~SMDS_DownQuadPyramid();
@@ -267,18 +298,21 @@ protected:
 
 class SMDS_DownPenta: public SMDS_Down3D
 {
+  friend class SMDS_UnstructuredGrid;
 public:
+  virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
+protected:
   SMDS_DownPenta(SMDS_UnstructuredGrid *grid);
   ~SMDS_DownPenta();
   virtual void addDownCell(int cellId, int lowCellId, unsigned char aType);
   virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes);
-protected:
 };
 
 class SMDS_DownQuadPenta: public SMDS_Down3D
 {
   friend class SMDS_UnstructuredGrid;
 public:
+  virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
 protected:
   SMDS_DownQuadPenta(SMDS_UnstructuredGrid *grid);
   ~SMDS_DownQuadPenta();
@@ -290,6 +324,7 @@ class SMDS_DownHexa: public SMDS_Down3D
 {
   friend class SMDS_UnstructuredGrid;
 public:
+  virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
 protected:
   SMDS_DownHexa(SMDS_UnstructuredGrid *grid);
   ~SMDS_DownHexa();
@@ -301,6 +336,7 @@ class SMDS_DownQuadHexa: public SMDS_Down3D
 {
   friend class SMDS_UnstructuredGrid;
 public:
+  virtual void getOrderedNodesOfFace(int cellId, std::vector<int>& orderedNodes);
 protected:
   SMDS_DownQuadHexa(SMDS_UnstructuredGrid *grid);
   ~SMDS_DownQuadHexa();
index 91acdb17a3bb434417ca8b13318304755f92bd87..bb757e852c5462b26a038ea27ccc99e477f5054a 100644 (file)
@@ -20,7 +20,7 @@
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-//  SMESH SMDS : implementaion of Salome mesh data structure
+//  SMESH SMDS : implementation of Salome mesh data structure
 //
 #ifndef _SMDS_FaceOfEdges_HeaderFile
 #define _SMDS_FaceOfEdges_HeaderFile
@@ -48,6 +48,7 @@ class SMDS_EXPORT SMDS_FaceOfEdges:public SMDS_MeshFace
                 
         SMDSAbs_ElementType GetType() const;
         virtual SMDSAbs_EntityType   GetEntityType() const;
+        virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes) {return false;};
         int NbNodes() const;
         int NbEdges() const;
         int NbFaces() const;
index f8c7025066f5b41cfdb67defce91595b477291ac..e7c66d7cf5d1217339641c6097b3b941b004749e 100644 (file)
@@ -43,6 +43,10 @@ public:
   {
     return SMDSEntity_Edge;
   }
+  virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
+  {
+    return false;
+  }
   int NbNodes() const;
   int NbEdges() const;
   friend bool operator<(const SMDS_LinearEdge& e1, const SMDS_LinearEdge& e2);
index 2c2aa6ed627323d979e1df6ed7a1d3b19f9e0e63..79f41cbbcaca9109e6aecc1856eae2e1c8174fc0 100644 (file)
@@ -209,6 +209,7 @@ SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
   if(!node){
     //if ( myNodes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
     //SMDS_MeshNode * node=new SMDS_MeshNode(ID, myMeshId, -1, x, y, z);
+    myNodeIDFactory->adjustMaxId(ID);
     SMDS_MeshNode * node = myNodePool->getNew();
     node->init(ID, myMeshId, -1, x, y, z);
     if (ID >= myNodes.size())
@@ -1453,6 +1454,7 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
                                    const SMDS_MeshNode    * nodes[],
                                    const int                nbnodes)
 {
+  // TODO use polymorphism, check number of nodes and type are unchanged.
   MYASSERT(0); // REVOIR LES TYPES
   // keep current nodes of elem
   set<const SMDS_MeshElement*> oldNodes;
@@ -1465,47 +1467,51 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
 
   // change nodes
   bool Ok = false;
-  SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(element);
-  switch ( elem->GetType() )
-  {
-  case SMDSAbs_0DElement: {
-    if ( SMDS_Mesh0DElement* elem0d = dynamic_cast<SMDS_Mesh0DElement*>( elem ))
-      Ok = elem0d->ChangeNode( nodes[0] );
-    break;
-  }
-  case SMDSAbs_Edge: {
-    if ( nbnodes == 2 ) {
-      if ( SMDS_VtkEdge* edge = dynamic_cast<SMDS_VtkEdge*>( elem ))
-        Ok = edge->ChangeNodes( nodes[0], nodes[1] );
-    }
-    else if ( nbnodes == 3 ) {
-      if ( SMDS_QuadraticEdge* edge = dynamic_cast<SMDS_QuadraticEdge*>( elem ))
-        Ok = edge->ChangeNodes( nodes[0], nodes[1], nodes[2] );
-    }
-    break;
-  }
-  case SMDSAbs_Face: {
-    if ( SMDS_FaceOfNodes* face = dynamic_cast<SMDS_FaceOfNodes*>( elem ))
-      Ok = face->ChangeNodes( nodes, nbnodes );
-    else
-      if ( SMDS_QuadraticFaceOfNodes* QF = dynamic_cast<SMDS_QuadraticFaceOfNodes*>( elem ))
-        Ok = QF->ChangeNodes( nodes, nbnodes );
-      else
-        if (SMDS_PolygonalFaceOfNodes* face = dynamic_cast<SMDS_PolygonalFaceOfNodes*>(elem))
-          Ok = face->ChangeNodes(nodes, nbnodes);
-    break;
-  }
-  case SMDSAbs_Volume: {
-    if ( SMDS_VolumeOfNodes* vol = dynamic_cast<SMDS_VolumeOfNodes*>( elem ))
-      Ok = vol->ChangeNodes( nodes, nbnodes );
-    else
-      if ( SMDS_QuadraticVolumeOfNodes* QV = dynamic_cast<SMDS_QuadraticVolumeOfNodes*>( elem ))
-        Ok = QV->ChangeNodes( nodes, nbnodes );
-    break;
-  }
-  default:
-    MESSAGE ( "WRONG ELEM TYPE");
-  }
+  SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element);
+  if (cell)
+    Ok = cell->ChangeNodes(nodes, nbnodes);
+
+//  SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(element);
+//  switch ( elem->GetType() )
+//  {
+//  case SMDSAbs_0DElement: {
+//    if ( SMDS_Mesh0DElement* elem0d = dynamic_cast<SMDS_Mesh0DElement*>( elem ))
+//      Ok = elem0d->ChangeNode( nodes[0] );
+//    break;
+//  }
+//  case SMDSAbs_Edge: {
+//    if ( nbnodes == 2 ) {
+//      if ( SMDS_VtkEdge* edge = dynamic_cast<SMDS_VtkEdge*>( elem ))
+//        Ok = edge->ChangeNodes( nodes[0], nodes[1] );
+//    }
+//    else if ( nbnodes == 3 ) {
+//      if ( SMDS_QuadraticEdge* edge = dynamic_cast<SMDS_QuadraticEdge*>( elem ))
+//        Ok = edge->ChangeNodes( nodes[0], nodes[1], nodes[2] );
+//    }
+//    break;
+//  }
+//  case SMDSAbs_Face: {
+//    if ( SMDS_FaceOfNodes* face = dynamic_cast<SMDS_FaceOfNodes*>( elem ))
+//      Ok = face->ChangeNodes( nodes, nbnodes );
+//    else
+//      if ( SMDS_QuadraticFaceOfNodes* QF = dynamic_cast<SMDS_QuadraticFaceOfNodes*>( elem ))
+//        Ok = QF->ChangeNodes( nodes, nbnodes );
+//      else
+//        if (SMDS_PolygonalFaceOfNodes* face = dynamic_cast<SMDS_PolygonalFaceOfNodes*>(elem))
+//          Ok = face->ChangeNodes(nodes, nbnodes);
+//    break;
+//  }
+//  case SMDSAbs_Volume: {
+//    if ( SMDS_VolumeOfNodes* vol = dynamic_cast<SMDS_VolumeOfNodes*>( elem ))
+//      Ok = vol->ChangeNodes( nodes, nbnodes );
+//    else
+//      if ( SMDS_QuadraticVolumeOfNodes* QV = dynamic_cast<SMDS_QuadraticVolumeOfNodes*>( elem ))
+//        Ok = QV->ChangeNodes( nodes, nbnodes );
+//    break;
+//  }
+//  default:
+//    MESSAGE ( "WRONG ELEM TYPE");
+//  }
 
   if ( Ok ) { // update InverseElements
 
@@ -1516,7 +1522,7 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
       it = oldNodes.find( nodes[i] );
       if ( it == oldNodes.end() )
         // new node
-        const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( elem );
+        const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( cell );
       else
         // remove from oldNodes a node that remains in elem
         oldNodes.erase( it );
@@ -1526,7 +1532,7 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
     {
       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
         (const_cast<SMDS_MeshElement *>( *it ));
-      n->RemoveInverseElement( elem );
+      n->RemoveInverseElement( cell );
     }
   }
 
index d827ab18e8ea31720e77631f154c77a35c9e8320..83204682a4fd83bfa915d5a6b96c2403b1fd922f 100644 (file)
@@ -66,7 +66,7 @@ public:
   static std::vector<SMDS_Mesh*> _meshList;
 
   //! actual nodes coordinates, cells definition and reverse connectivity are stored in a vtkUnstructuredGrid
-  inline vtkUnstructuredGrid* getGrid() {return myGrid; };
+  inline SMDS_UnstructuredGrid* getGrid() {return myGrid; };
   inline int getMeshId() {return myMeshId; };
 
   SMDS_NodeIteratorPtr nodesIterator(bool idInceasingOrder=false) const;
@@ -573,7 +573,6 @@ public:
   void incrementCellsCapacity(int nbCells);
   void adjustStructure();
   void dumpGrid(string ficdump="dumpGrid");
-
   static int chunkSize;
 
 protected:
@@ -608,8 +607,9 @@ protected:
   inline void adjustmyCellsCapacity(int ID)
   {
     assert(ID >= 0);
+    myElementIDFactory->adjustMaxId(ID);
     if (ID >= myCells.size())
-        myCells.resize(ID+SMDS_Mesh::chunkSize,0);
+      myCells.resize(ID+SMDS_Mesh::chunkSize,0);
   };
 
   // Fields PRIVATE
index 355986a4d796906aed7e3e307911e1b40c15d5d0..b137222914dde4c813ee0d811208c01c2df4534d 100644 (file)
@@ -35,6 +35,7 @@ class SMDS_EXPORT SMDS_Mesh0DElement: public SMDS_MeshCell
  public:
   SMDS_Mesh0DElement (const SMDS_MeshNode * node);
   bool ChangeNode (const SMDS_MeshNode * node);
+  virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes) {return false;};
   void Print (std::ostream & OS) const;
 
   SMDSAbs_ElementType GetType() const;
index 96108c0950178d23df47bd2f555de3730e5857f8..aa5ba12c9dc44e2b6c2b9e1cb5f416752e928857 100644 (file)
@@ -12,6 +12,9 @@ class SMDS_EXPORT SMDS_MeshCell: public SMDS_MeshElement
 public:
   SMDS_MeshCell();
   virtual ~SMDS_MeshCell();
+
+  virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)= 0;
+
   inline void setVtkId(int vtkId)
   {
     myVtkID = vtkId;
index a1546e9020f4f512725fda2d14d3247bac1deca3..ccb2ad658179dc7de90abcd636be6f70ad5945ff 100644 (file)
@@ -111,3 +111,4 @@ void SMDS_MeshIDFactory::emptyPool(int maxId)
        myMaxID = maxId-1;
        myPoolOfID.clear();
 }
+
index 9f1393bd0e7259541c04705994c29ee696988947..e936d0fed80cdd1b751eb3e202e5cfd37bc62dbe 100644 (file)
@@ -45,6 +45,7 @@ public:
   SMDS_Mesh* GetMesh();
   inline bool isPoolIdEmpty() { return myPoolOfID.empty(); };
   void emptyPool(int maxId);
+  inline void adjustMaxId(int ID) { if (ID > myMaxID) myMaxID = ID;};
 protected:
   SMDS_MeshIDFactory();
   int myMaxID;
index 35690ac539bf75a6664538c48b4979bb3c2efb8e..1212276b8284dc6d1cc7634229115ea55f76399f 100644 (file)
@@ -303,9 +303,10 @@ void SMDS_UnstructuredGrid::setCellIdToDownId(int vtkCellId, int downId)
  *  Downward connectivity is no more valid if vtkUnstructuredGrid is modified.
  *
  */
-void SMDS_UnstructuredGrid::BuildDownwardConnectivity()
+void SMDS_UnstructuredGrid::BuildDownwardConnectivity(bool withEdges)
 {
   MESSAGE("SMDS_UnstructuredGrid::BuildDownwardConnectivity");CHRONO(2);
+  // TODO calcul partiel sans edges
 
   // --- erase previous data if any
 
@@ -665,3 +666,107 @@ void SMDS_UnstructuredGrid::BuildDownwardConnectivity()
     }CHRONOSTOP(24);CHRONOSTOP(2);
   _counters->stats();
 }
+
+/*! Get the neighbors of a cell.
+ * Only the neighbors having the dimension of the cell are taken into account
+ * (neighbors of a volume are the volumes sharing a face with this volume,
+ *  neighbors of a face are the faces sharing an edge with this face...).
+ * @param neighborsVtkIds vector of neighbors vtk id's to fill (reserve enough space).
+ * @param downIds downward id's of cells of dimension n-1, to fill (reserve enough space).
+ * @param downTypes vtk types of cells of dimension n-1, to fill (reserve enough space).
+ * @param vtkId the vtk id of the cell
+ * @return number of neighbors
+ */
+int SMDS_UnstructuredGrid::GetNeighbors(int* neighborsVtkIds, int* downIds, unsigned char* downTypes, int vtkId)
+{
+  int vtkType = this->GetCellType(vtkId);
+  int cellDim = SMDS_Downward::getCellDimension(vtkType);
+  if (cellDim != 3)
+    return 0; // TODO voisins des faces ou edges
+  int cellId = this->_cellIdToDownId[vtkId];
+
+  int nbCells = _downArray[vtkType]->getNumberOfDownCells(cellId);
+  const int *downCells = _downArray[vtkType]->getDownCells(cellId);
+  const unsigned char* downTyp = _downArray[vtkType]->getDownTypes(cellId);
+
+  // --- iteration on faces of the 3D cell.
+
+  int nb = 0;
+  for (int i = 0; i < nbCells; i++)
+    {
+      int downId = downCells[i];
+      int cellType = downTyp[i];
+      int nbUp = _downArray[cellType]->getNumberOfUpCells(downId);
+      const int *upCells = _downArray[cellType]->getUpCells(downId);
+      const unsigned char* upTypes = _downArray[cellType]->getUpTypes(downId);
+
+      // --- max 2 upCells, one is this cell, the other is a neighbor
+
+      for (int j = 0; j < nbUp; j++)
+        {
+          if ((upCells[j] == cellId) && (upTypes[j] == vtkType))
+            continue;
+          int vtkNeighbor = _downArray[upTypes[j]]->getVtkCellId(upCells[j]);
+          neighborsVtkIds[nb] = vtkNeighbor;
+          downIds[nb] = downId;
+          downTypes[nb] = cellType;
+          nb++;
+        }
+      if (nb >= NBMAXNEIGHBORS)
+        assert(0);
+    }
+  return nb;
+}
+
+/*! get the node id's of a cell.
+ * The cell is defined by it's downward connectivity id and type.
+ * @param nodeSet set of of vtk node id's to fill.
+ * @param downId downward connectivity id of the cell.
+ * @param downType type of cell.
+ */
+void SMDS_UnstructuredGrid::GetNodeIds(std::set<int>& nodeSet, int downId, unsigned char downType)
+{
+  _downArray[downType]->getNodeIds(downId, nodeSet);
+}
+
+/*! change some nodes in cell without modifying type or internal connectivity.
+ * Nodes inverse connectivity is maintained up to date.
+ * @param vtkVolId vtk id of the cell
+ * @param localClonedNodeIds map old node id to new node id.
+ */
+void SMDS_UnstructuredGrid::ModifyCellNodes(int vtkVolId, std::map<int, int> localClonedNodeIds)
+{
+  vtkIdType npts = 0;
+  vtkIdType *pts; // will refer to the point id's of the face
+  this->GetCellPoints(vtkVolId, npts, pts);
+  for (int i = 0; i < npts; i++)
+    {
+      if (localClonedNodeIds.count(pts[i]))
+        {
+          vtkIdType oldpt = pts[i];
+          pts[i] = localClonedNodeIds[oldpt];
+          //MESSAGE(oldpt << " --> " << pts[i]);
+          //this->RemoveReferenceToCell(oldpt, vtkVolId);
+          //this->AddReferenceToCell(pts[i], vtkVolId);
+        }
+    }
+}
+
+/*! Create a volume (prism or hexahedron) by duplication of a face.
+ * the nodes of the new face are already created.
+ * @param vtkVolId vtk id of a volume containing the face, to get an orientation for the face.
+ * @param localClonedNodeIds map old node id to new node id.
+ * @return vtk id of the new volume.
+ */
+int SMDS_UnstructuredGrid::getOrderedNodesOfFace(int vtkVolId, std::vector<int>& orderedNodes)
+{
+  int vtkType = this->GetCellType(vtkVolId);
+  int cellDim = SMDS_Downward::getCellDimension(vtkType);
+  if (cellDim != 3)
+    return 0;
+  SMDS_Down3D *downvol = static_cast<SMDS_Down3D*> (_downArray[vtkType]);
+  int downVolId = this->_cellIdToDownId[vtkVolId];
+  downvol->getOrderedNodesOfFace(downVolId, orderedNodes);
+  return orderedNodes.size();
+}
+
index 30a0747537d8db88ac7e2e53e09231bcbe4c6dd4..d204a5c89f47d7cc62e5942359411135612d59ab 100644 (file)
@@ -9,10 +9,14 @@
 #define        _SMDS_UNSTRUCTUREDGRID_HXX
 
 #include <vector>
+#include <set>
+#include <map>
 
 #include <vtkUnstructuredGrid.h>
 #include "chrono.hxx"
 
+#define NBMAXNEIGHBORS 10
+
 class SMDS_Downward;
 class SMDS_Mesh;
 
@@ -29,7 +33,11 @@ public:
 
   int CellIdToDownId(int vtkCellId);
   void setCellIdToDownId(int vtkCellId, int downId);
-  void BuildDownwardConnectivity();
+  void BuildDownwardConnectivity(bool withEdges);
+  int GetNeighbors(int* neighborsVtkIds, int* downIds, unsigned char* downTypes, int vtkId);
+  void GetNodeIds(std::set<int>& nodeSet, int downId, unsigned char downType);
+  void ModifyCellNodes(int vtkVolId, std::map<int, int> localClonedNodeIds);
+  int getOrderedNodesOfFace(int vtkVolId, std::vector<int>& orderedNodes);
   vtkCellLinks* GetLinks()
   {
     return Links;
@@ -39,6 +47,7 @@ public:
     return _downArray[vtkType];
   }
   static SMDS_UnstructuredGrid* New();
+  SMDS_Mesh *_mesh;
 protected:
   SMDS_UnstructuredGrid();
   ~SMDS_UnstructuredGrid();
@@ -47,7 +56,6 @@ protected:
                 vtkCellArray* newConnectivity, vtkIdTypeArray* newLocations, vtkIdType* pointsCell, int& alreadyCopied,
                 int start, int end);
 
-  SMDS_Mesh *_mesh;
   std::vector<int> _cellIdToDownId; //!< convert vtk Id to downward[vtkType] id, initialized with -1
   std::vector<unsigned char> _downTypes;
   std::vector<SMDS_Downward*> _downArray;
index 1b3c8374fbb8dc2267fc7ff6cca0a150cc28c2d8..1b93c68a079ec9622d324faad5b89e150f7c6a60 100644 (file)
@@ -56,6 +56,7 @@ class SMDS_EXPORT SMDS_VolumeOfFaces:public SMDS_MeshVolume
                            const SMDS_MeshFace * face6);
 
         virtual SMDSAbs_EntityType GetEntityType() const;
+        virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes) {return false;};
         void Print(std::ostream & OS) const;
 
         int NbFaces() const;
index 34745b44f81c3b2914cc5be365f4ccfe0cf96347..923a6212b679e922980a4753e436c840fdb7bf08 100644 (file)
@@ -37,6 +37,13 @@ void SMDS_VtkEdge::init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
 bool SMDS_VtkEdge::ChangeNodes(const SMDS_MeshNode * node1,
                                const SMDS_MeshNode * node2)
 {
+  // TODO remove
+  return true;
+}
+
+bool SMDS_VtkEdge::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
+{
+  // TODO
   return true;
 }
 
index f3772114105805cc6c4e8f0450e8e3c0318c4541..b68b904f7f69c61ca9d9d08d0198382e277a4702 100644 (file)
@@ -16,6 +16,7 @@ public:
   ~SMDS_VtkEdge();
   void init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh);
   bool ChangeNodes(const SMDS_MeshNode * node1, const SMDS_MeshNode * node2);
+  virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes);
 
   void Print(std::ostream & OS) const;
   int NbNodes() const;
index ade2f5ce02a6699cb51db329e94390d0c419a445..763219c39107ea58a4a4bb9de9c1a82245bcf74a 100644 (file)
@@ -51,6 +51,7 @@ void SMDS_VtkFace::init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
 
 bool SMDS_VtkFace::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
 {
+  // TODO
   return true;
 }
 
index c8865d6ba589371f03791e364d4a439fa077ba94..f333a8267ee795abd6a9acdc4a4b605d7079b25f 100644 (file)
@@ -61,7 +61,7 @@ void SMDS_VtkVolume::init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
 bool SMDS_VtkVolume::ChangeNodes(const SMDS_MeshNode* nodes[],
                                  const int nbNodes)
 {
-  // utilise dans SMDS_Mesh
+  // TODO utilise dans SMDS_Mesh
   return true;
 }
 
index 2a52ec831fd3861907fda339766eed612d04c87b..ac727041e4b1eade6f5126c7255e6e3bb587b1b4 100644 (file)
@@ -36,6 +36,7 @@
 #include "SMDS_QuadraticFaceOfNodes.hxx"
 #include "SMDS_MeshGroup.hxx"
 #include "SMDS_LinearEdge.hxx"
+#include "SMDS_Downward.hxx"
 
 #include "SMESHDS_Group.hxx"
 #include "SMESHDS_Mesh.hxx"
@@ -798,7 +799,7 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
       return false;
 
     //MESSAGE( endl << tr1 << tr2 );
-
+    // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
     GetMeshDS()->ChangeElementNodes( tr1, aNodes, 4 );
     myLastCreatedElems.Append(tr1);
     GetMeshDS()->RemoveElement( tr2 );
@@ -844,6 +845,7 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
   aNodes[6] = N2[3];
   aNodes[7] = N1[5];
 
+  // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
   GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
   myLastCreatedElems.Append(tr1);
   GetMeshDS()->RemoveElement( tr2 );
@@ -1017,11 +1019,13 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
 
       if ( aBadRate1 <= aBadRate2 ) {
         // tr1 + tr2 is better
+        // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
         aMesh->ChangeElementNodes( elem, aNodes, 3 );
         newElem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
       }
       else {
         // tr3 + tr4 is better
+        // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
         aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
         newElem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
       }
@@ -1097,6 +1101,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
         newElem = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
                                  aNodes[7], aNodes[4], newN );
       }
+      // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
       aMesh->ChangeElementNodes( elem, N, 6 );
 
     } // quadratic case
@@ -1729,10 +1734,12 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
       int aShapeId = FindShape( elem );
       const SMDS_MeshElement* newElem = 0;
       if ( the13Diag ) {
+        // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
         aMesh->ChangeElementNodes( elem, aNodes, 3 );
         newElem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
       }
       else {
+        // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
         aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
         newElem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
       }
@@ -1818,6 +1825,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
                                  aNodes[7], aNodes[4], newN );
       }
       myLastCreatedElems.Append(newElem);
+      // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
       aMesh->ChangeElementNodes( elem, N, 6 );
       // put a new triangle on the same shape and add to the same groups
       if ( aShapeId )
@@ -2119,11 +2127,13 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
           mapLi_listEl.erase( *link12 );
           if(tr1->NbNodes()==3) {
             if( tr1->GetID() < tr2->GetID() ) {
+              // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
               aMesh->ChangeElementNodes( tr1, n12, 4 );
               myLastCreatedElems.Append(tr1);
               aMesh->RemoveElement( tr2 );
             }
             else {
+              // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
               aMesh->ChangeElementNodes( tr2, n12, 4 );
               myLastCreatedElems.Append(tr2);
               aMesh->RemoveElement( tr1);
@@ -2146,11 +2156,13 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
             aNodes[6] = N2[3];
             aNodes[7] = N1[5];
             if( tr1->GetID() < tr2->GetID() ) {
+              // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
               GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
               myLastCreatedElems.Append(tr1);
               GetMeshDS()->RemoveElement( tr2 );
             }
             else {
+              // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
               GetMeshDS()->ChangeElementNodes( tr2, aNodes, 8 );
               myLastCreatedElems.Append(tr2);
               GetMeshDS()->RemoveElement( tr1 );
@@ -2164,11 +2176,13 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
           mapLi_listEl.erase( *link13 );
           if(tr1->NbNodes()==3) {
             if( tr1->GetID() < tr2->GetID() ) {
+              // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
               aMesh->ChangeElementNodes( tr1, n13, 4 );
               myLastCreatedElems.Append(tr1);
               aMesh->RemoveElement( tr3 );
             }
             else {
+              // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
               aMesh->ChangeElementNodes( tr3, n13, 4 );
               myLastCreatedElems.Append(tr3);
               aMesh->RemoveElement( tr1 );
@@ -2191,11 +2205,13 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
             aNodes[6] = N2[3];
             aNodes[7] = N1[5];
             if( tr1->GetID() < tr2->GetID() ) {
+              // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
               GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
               myLastCreatedElems.Append(tr1);
               GetMeshDS()->RemoveElement( tr3 );
             }
             else {
+              // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
               GetMeshDS()->ChangeElementNodes( tr3, aNodes, 8 );
               myLastCreatedElems.Append(tr3);
               GetMeshDS()->RemoveElement( tr1 );
@@ -3872,6 +3888,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
               if ( !f )
                 myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
               else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
+                // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
                 aMesh->ChangeElementNodes( f, nodes, nbn );
               break;
             }
@@ -3880,6 +3897,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
               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 ))
+                // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
                 aMesh->ChangeElementNodes( f, nodes, nbn );
               break;
             }
@@ -3900,6 +3918,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
                     tmpnodes[3] = nodes[1];
                     tmpnodes[4] = nodes[3];
                     tmpnodes[5] = nodes[5];
+                    // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
                     aMesh->ChangeElementNodes( f, tmpnodes, nbn );
                   }
                 }
@@ -3920,6 +3939,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
                     tmpnodes[5] = nodes[3];
                     tmpnodes[6] = nodes[5];
                     tmpnodes[7] = nodes[7];
+                    // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
                     aMesh->ChangeElementNodes( f, tmpnodes, nbn );
                   }
                 }
@@ -3930,6 +3950,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
                 if ( !f )
                   myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes));
                 else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
+                  // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
                   aMesh->ChangeElementNodes( f, nodes, nbn );
               }
             }
@@ -8645,6 +8666,7 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
     newNodes[ 1 ] = linkNodes[ i2 ];
     newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ];
     newNodes[ 3 ] = nodes[ i4 ];
+    // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
     aMesh->ChangeElementNodes( theFace, newNodes, iSplit == iBestQuad ? 4 : 3 );
   } // end if(!theFace->IsQuadratic())
   else { // theFace is quadratic
@@ -9740,6 +9762,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
         //         elemIDsToRemove.push_back( e->GetID() );
         //       else
         if ( nbReplaced )
+          // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
           aMesh->ChangeElementNodes( e, & nodes[0], nbNodes );
       }
     }
@@ -10234,6 +10257,192 @@ bool SMESH_MeshEditor::DoubleNodesInRegion( const TIDSortedElemSet& theElems,
   return DoubleNodes( theElems, theNodesNot, anAffected );
 }
 
+/*!
+ * \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.
+ * @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<TIDSortedElemSet>& theElems,
+                                                     bool createJointElems)
+{
+  MESSAGE("------------------------------------------------------");
+  MESSAGE("SMESH_MeshEditor::CreateJointElementsOnGroupBoundaries");
+  MESSAGE("------------------------------------------------------");
+
+  SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
+  meshDS->BuildDownWardConnectivity(false);
+  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 nodes shared by 2 or more domains, with their domain indexes
+
+  std::map<DownIdType, std::map<int,int>, DownIdCompare> faceDomains; // 2x(id domain --> id volume)
+  std::map<int, std::map<int,int> > nodeDomains; //oldId ->  (domainId -> newId)
+  faceDomains.clear();
+  nodeDomains.clear();
+  std::map<int,int> emptyMap;
+  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 = meshDS->fromSmdsToVtk(anElem->getId());
+          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
+                    }
+                }
+            }
+        }
+    }
+
+  MESSAGE("Number of shared faces " << faceDomains.size());
+
+  // --- for each shared face, get the nodes
+  //     for each node, for each domain of the face, create a clone of the node
+
+  std::map<DownIdType, std::map<int,int>, DownIdCompare>::iterator itface = faceDomains.begin();
+  for( ; itface != faceDomains.end();++itface )
+    {
+      DownIdType face = itface->first;
+      std::map<int,int> domvol = itface->second;
+      std::set<int> oldNodes;
+      oldNodes.clear();
+      grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
+      std::set<int>::iterator itn = oldNodes.begin();
+      for (;itn != oldNodes.end(); ++itn)
+        {
+          int oldId = *itn;
+          if (!nodeDomains.count(oldId))
+            nodeDomains[oldId] = emptyMap; // create an empty entry for node
+          std::map<int,int>::iterator itdom = domvol.begin();
+          for(; itdom != domvol.end(); ++itdom)
+            {
+              int idom = itdom->first;
+              if ( nodeDomains[oldId].empty() )
+                nodeDomains[oldId][idom] = oldId; // keep the old node in the first domain
+              else
+                {
+                  double *coords = grid->GetPoint(oldId);
+                  SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]);
+                  int newId = newNode->GetID();
+                  nodeDomains[oldId][idom] = newId; // cloned node for other 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
+
+  if (createJointElems)
+    {
+      itface = faceDomains.begin();
+      for( ; itface != faceDomains.end();++itface )
+        {
+          DownIdType face = itface->first;
+          std::set<int> oldNodes;
+          std::set<int>::iterator itn;
+          oldNodes.clear();
+          grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
+          std::map<int,int> localClonedNodeIds;
+
+          std::map<int,int> domvol = itface->second;
+          std::map<int,int>::iterator itdom = domvol.begin();
+          int dom1 = itdom->first;
+          int vtkVolId = itdom->second;
+          itdom++;
+          int dom2 = itdom->first;
+
+          localClonedNodeIds.clear();
+          for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn)
+            {
+              int oldId = *itn;
+              int refid = oldId;
+              if (nodeDomains[oldId].count(dom1))
+                refid = nodeDomains[oldId][dom1];
+              else
+                MESSAGE("--- problem domain node " << dom1 << " " << oldId);
+              int newid = oldId;
+              if (nodeDomains[oldId].count(dom2))
+                newid = nodeDomains[oldId][dom2];
+              else
+                MESSAGE("--- problem domain node " << dom2 << " " << oldId);
+              localClonedNodeIds[oldId] = newid;
+            }
+          int smdsId = meshDS->fromVtkToSmds(vtkVolId);
+          meshDS->extrudeVolumeFromFace(smdsId, localClonedNodeIds);
+        }
+    }
+
+  // --- iterate on shared faces (volumes to modify, face to extrude)
+  //     get node id's of the face (id SMDS = id VTK)
+  //     replace old nodes by new nodes in volumes, and update inverse connectivity
+
+  itface = faceDomains.begin();
+  for( ; itface != faceDomains.end();++itface )
+    {
+      DownIdType face = itface->first;
+      std::set<int> oldNodes;
+      std::set<int>::iterator itn;
+      oldNodes.clear();
+      grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
+      std::map<int,int> localClonedNodeIds;
+
+      std::map<int,int> domvol = itface->second;
+      std::map<int,int>::iterator itdom = domvol.begin();
+      for(; itdom != domvol.end(); ++itdom)
+        {
+          int idom = itdom->first;
+          int vtkVolId = itdom->second;
+          localClonedNodeIds.clear();
+          for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn)
+            {
+              int oldId = *itn;
+              if (nodeDomains[oldId].count(idom))
+                localClonedNodeIds[oldId] = nodeDomains[oldId][idom];
+            }
+          int smdsId = meshDS->fromVtkToSmds(vtkVolId);
+          meshDS->ModifyCellNodes(smdsId, localClonedNodeIds);
+        }
+    }
+  grid->BuildLinks();
+
+  // TODO replace also old nodes by new nodes in faces and edges
+}
+
 //================================================================================
 /*!
  * \brief Generated skin mesh (containing 2D cells) from 3D mesh
index d9f4b5d28a737e19894bb570146b6c9f0cb7f594..cef86b4afece70971764909d2ae49592f5b97439 100644 (file)
@@ -627,6 +627,9 @@ public:
                             const TIDSortedElemSet& theNodesNot,
                             const TopoDS_Shape&     theShape );
   
+  bool DoubleNodesOnGroupBoundaries( const std::vector<TIDSortedElemSet>& theElems,
+                                     bool createJointElems);
+
   /*!
    * \brief Generated skin mesh (containing 2D cells) from 3D mesh
    * The created 2D mesh elements based on nodes of free faces of boundary volumes
index a7afa4c9f033987a64faea65138636793a1d95dd..0afc862cd7772aef604f53a5cf1c9872b7f31506 100644 (file)
@@ -33,6 +33,7 @@
 #include "SMDS_EdgePosition.hxx"
 #include "SMDS_FacePosition.hxx"
 #include "SMDS_SpacePosition.hxx"
+#include "SMDS_Downward.hxx"
 #include "SMESHDS_GroupOnGeom.hxx"
 
 #include <Standard_ErrorHandler.hxx>
@@ -1914,8 +1915,6 @@ void SMESHDS_Mesh::compactMesh()
        myVtkIndex.swap(newVtkToSmds);
        MESSAGE("myCells.size()=" << myCells.size() << " myIDElements.size()=" << myIDElements.size() << " myVtkIndex.size()=" << myVtkIndex.size() );
 
-       myGrid->BuildDownwardConnectivity();
-
        // ---TODO: myNodes, myElements in submeshes
 
 //    map<int,SMESHDS_SubMesh*>::iterator it = myShapeIndexToSubMesh.begin();
@@ -1926,3 +1925,53 @@ void SMESHDS_Mesh::compactMesh()
 
 }
 
+void SMESHDS_Mesh::BuildDownWardConnectivity(bool withEdges)
+{
+  myGrid->BuildDownwardConnectivity(withEdges);
+}
+
+/*! change some nodes in cell without modifying type or internal connectivity.
+ * Nodes inverse connectivity is maintained up to date.
+ * @param smdsVolId smds id of the cell.
+ * @param localClonedNodeIds map old node id to new node id.
+ * @return ok if success.
+ */
+bool SMESHDS_Mesh::ModifyCellNodes(int smdsVolId, std::map<int,int> localClonedNodeIds)
+{
+  int vtkVolId = this->fromSmdsToVtk(smdsVolId);
+  myGrid->ModifyCellNodes(vtkVolId, localClonedNodeIds);
+  return true;
+}
+
+/*! Create a volume (prism or hexahedron) by duplication of a face.
+ * the nodes of the new face are already created.
+ * @param vtkVolId vtk id of a volume containing the face, to get an orientation for the face.
+ * @param localClonedNodeIds map old node id to new node id. The old nodes define the face in the volume.
+ * @return ok if success.
+ */
+bool SMESHDS_Mesh::extrudeVolumeFromFace(int smdsVolId, std::map<int,int> localClonedNodeIds)
+{
+  int vtkVolId = this->fromSmdsToVtk(smdsVolId);
+  //MESSAGE(smdsVolId << " " << vtkVolId);
+  vector<int> orderedNodes;
+  orderedNodes.clear();
+  map<int, int>::iterator it = localClonedNodeIds.begin();
+  for (; it != localClonedNodeIds.end(); ++it)
+    orderedNodes.push_back(it->first);
+
+  int nbNodes = myGrid->getOrderedNodesOfFace(vtkVolId, orderedNodes);
+  if (nbNodes == 3)
+    {
+      int newVtkVolId =myElementIDFactory->GetFreeID();
+      SMDS_MeshVolume *vol = this->AddVolumeWithID(orderedNodes[0],
+                                                   orderedNodes[1],
+                                                   orderedNodes[2],
+                                                   localClonedNodeIds[orderedNodes[0]],
+                                                   localClonedNodeIds[orderedNodes[1]],
+                                                   localClonedNodeIds[orderedNodes[2]],
+                                                   newVtkVolId);
+    }
+
+  // TODO update subshape list of elements and nodes
+  return true;
+}
index b5ecf2988b9d9702b751d07b911a668289ec86a2..70af413ab3e9d89e32cf953e55fbc15e81dbd8b7 100644 (file)
@@ -56,6 +56,7 @@
 #include "SMESHDS_DataMapOfShape.hxx"
 
 class SMESHDS_GroupBase;
+class DownIdType;
 
 class SMESHDS_EXPORT SMESHDS_Mesh:public SMDS_Mesh{
 public:
@@ -397,6 +398,8 @@ public:
   bool ChangePolyhedronNodes(const SMDS_MeshElement * elem,
                              std::vector<const SMDS_MeshNode*> nodes,
                              std::vector<int>                  quantities);
+  bool ModifyCellNodes(int smdsVolId, std::map<int,int> localClonedNodeIds);
+  bool extrudeVolumeFromFace(int smdsVolId, std::map<int,int> localClonedNodeIds);
   void Renumber (const bool isNodes, const int startID=1, const int deltaID=1);
 
   void SetNodeInVolume(SMDS_MeshNode * aNode, const TopoDS_Shell & S);
@@ -440,6 +443,7 @@ public:
   bool IsGroupOfSubShapes (const TopoDS_Shape& aSubShape) const;
 
   void compactMesh();
+  void BuildDownWardConnectivity(bool withEdges);
 
   ~SMESHDS_Mesh();
   
index 0ccfca68126d25db5e547c019622c436ad27f163..f573ba1672eb528d53d913d0ee49fe3d15c6d670 100644 (file)
@@ -4766,3 +4766,51 @@ CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
   return aResult;
 }
+
+//================================================================================
+/*!
+ * \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.
+ * @param theDomains - list of groups of volumes
+ * @param createJointElems - if TRUE, create the elements
+ * @return TRUE if operation has been completed successfully, FALSE otherwise
+ */
+//================================================================================
+
+CORBA::Boolean SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
+                                                                 CORBA::Boolean createJointElems )
+{
+  initData();
+
+  ::SMESH_MeshEditor aMeshEditor( myMesh );
+
+  SMESHDS_Mesh* aMeshDS = GetMeshDS();
+
+  vector<TIDSortedElemSet> domains;
+  domains.clear();
+
+  for ( int i = 0, n = theDomains.length(); i < n; i++ )
+  {
+    SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
+    if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
+    {
+      TIDSortedElemSet domain;
+      domain.clear();
+      domains.push_back(domain);
+      SMESH::long_array_var anIDs = aGrp->GetIDs();
+      arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
+    }
+  }
+
+  bool aResult = aMeshEditor.DoubleNodesOnGroupBoundaries( domains, createJointElems );
+
+  storeResult( aMeshEditor) ;
+
+  // Update Python script
+  TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
+      << ", " << createJointElems << " )";
+  return aResult;
+}
index 046573b17fd210f36dc418d0722502e78fe18f5f..cac9240667accd8404b7906f39df088fa31473d2 100644 (file)
@@ -647,6 +647,20 @@ public:
     */
     CORBA::Boolean Make2DMeshFrom3D();
 
+    /*!
+     * \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.
+     * @param theDomains - list of groups of volumes
+     * @param createJointElems - if TRUE, create the elements
+     * @return TRUE if operation has been completed successfully, FALSE otherwise
+     */
+  CORBA::Boolean DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
+                                               CORBA::Boolean createJointElems );
+
+
  private: //!< private methods
 
   SMESHDS_Mesh * GetMeshDS() { return myMesh->GetMeshDS(); }
index 5e923300583d75c95884613ae2b3990b5aef2240..96c77da34d09d8ff32afe464df0e3d6dabcf1376 100644 (file)
@@ -3719,6 +3719,17 @@ class Mesh:
     #  @ingroup l2_modif_edit
     def DoubleNodeElemGroupsInRegion(self, theElems, theNodesNot, theShape):
         return self.editor.DoubleNodeElemGroupsInRegion(theElems, theNodesNot, theShape)
+        
+    ## 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.
+    # @param theDomains - list of groups of volumes
+    # @param createJointElems - if TRUE, create the elements
+    # @return TRUE if operation has been completed successfully, FALSE otherwise
+    def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems ):
+       return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems )
 
 ## The mother class to define algorithm, it is not recommended to use it directly.
 #