Salome HOME
Copyright update 2021
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
index 1d7ba140b7005d9644b21af7cd56d99a6eac3bb0..dab719240b8241316e6fd93649d7a36561d5be64 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2021  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
@@ -63,12 +63,12 @@ int SMDS_Mesh::chunkSize = 1024;
 //================================================================================
 /*!
  * \brief Raise an exception if free memory (ram+swap) too low
- * \param doNotRaise - if true, suppres exception, just return free memory size
+ * \param doNotRaise - if true, suppress exception, just return free memory size
  * \retval int - amount of available memory in MB or negative number in failure case
  */
 //================================================================================
 
-int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
+int SMDS_Mesh::CheckMemory(const bool doNotRaise)
 {
   return -1;
 #if !defined WIN32 && !defined __APPLE__
@@ -831,6 +831,8 @@ SMDS_Mesh::AddPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*> & nod
 {
   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
 
+  if ( nodes.empty() )
+    throw std::invalid_argument("Polygon without nodes is forbidden");
   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
     cell->init( SMDSEntity_Polygon, nodes );
@@ -874,6 +876,8 @@ SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*> &
                                        const int                                 ID)
 {
   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( nodes.empty() )
+    throw std::invalid_argument("Polygon without nodes is forbidden");
   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
     cell->init( SMDSEntity_Quad_Polygon, nodes );
@@ -1044,6 +1048,31 @@ bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
   return found;
 }
 
+//=======================================================================
+//function : ChangePolyhedronNodes
+//purpose  :
+//=======================================================================
+
+bool SMDS_Mesh::ChangePolyhedronNodes(const SMDS_MeshElement *                 element,
+                                      const std::vector<const SMDS_MeshNode*>& nodes,
+                                      const std::vector<int>&                  quantities)
+{
+  // keep current nodes of element
+  std::set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
+
+  // change nodes
+  bool Ok = false;
+  if ( const SMDS_MeshVolume* vol = DownCast<SMDS_MeshVolume>( element ))
+    Ok = vol->ChangeNodes( nodes, quantities );
+
+  if ( Ok )
+  {
+    setMyModified();
+    updateInverseElements( element, &nodes[0], nodes.size(), oldNodes );
+  }
+  return Ok;
+}
+
 //=======================================================================
 //function : ChangeElementNodes
 //purpose  :
@@ -1062,14 +1091,30 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
     Ok = cell->ChangeNodes(nodes, nbnodes);
 
   if ( Ok )
+  {
     setMyModified();
+    updateInverseElements( element, nodes, nbnodes, oldNodes );
+  }
+  return Ok;
+}
 
-  if ( Ok && GetGrid()->HasLinks() ) // update InverseElements
+//=======================================================================
+//function : updateInverseElements
+//purpose  : update InverseElements when element changes node
+//=======================================================================
+
+void SMDS_Mesh::updateInverseElements( const SMDS_MeshElement *        element,
+                                       const SMDS_MeshNode* const*     nodes,
+                                       const int                       nbnodes,
+                                       std::set<const SMDS_MeshNode*>& oldNodes )
+{
+  if ( GetGrid()->HasLinks() ) // update InverseElements
   {
     std::set<const SMDS_MeshNode*>::iterator it;
 
     // AddInverseElement to new nodes
-    for ( int i = 0; i < nbnodes; i++ ) {
+    for ( int i = 0; i < nbnodes; i++ )
+    {
       it = oldNodes.find( nodes[i] );
       if ( it == oldNodes.end() )
         // new node
@@ -1086,7 +1131,6 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
     }
   }
 
-  return Ok;
 }
 
 const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
@@ -1542,8 +1586,9 @@ SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator() const
 
 SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
 {
+  int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
   return myCellFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::GeomFilter( type ),
-                                                          myInfo.NbElements( type ));
+                                                          nbElems);
 }
 
 SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
@@ -1552,8 +1597,9 @@ SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) c
   {
     return myNodeFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::NonNullFilter );
   }
+  int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
   return myCellFactory->GetIterator<SMDS_ElemIterator>( new SMDS_MeshElement::EntityFilter( type ),
-                                                        myInfo.NbElements( type ));
+                                                        nbElems);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1571,8 +1617,9 @@ SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
     return myNodeFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
 
   default:
+    int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
     return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( type ),
-                                                    myInfo.NbElements( type ));
+                                                    nbElems);
   }
   return SMDS_ElemIteratorPtr();
 }
@@ -1584,8 +1631,9 @@ SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
 {
   typedef SMDS_EdgeIterator TIterator;
+  int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbEdges();
   return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Edge ),
-                                                  myInfo.NbEdges());
+                                                  nbElems);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1595,8 +1643,9 @@ SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
 {
   typedef SMDS_FaceIterator TIterator;
+  int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbFaces();
   return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Face ),
-                                                  myInfo.NbFaces());
+                                                  nbElems);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1606,19 +1655,24 @@ SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
 {
   typedef SMDS_VolumeIterator TIterator;
+  int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbVolumes();
   return
     myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Volume ),
-                                             myInfo.NbVolumes());
+                                             nbElems );
 }
 
-SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int shapeID, size_t nbElemsToReturn) const
+SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int                  shapeID,
+                                                   size_t               nbElemsToReturn,
+                                                   const SMDS_MeshNode* sm1stNode) const
 {
-  return myNodeFactory->GetShapeIterator< SMDS_NodeIterator >( shapeID, nbElemsToReturn );
+  return myNodeFactory->GetShapeIterator< SMDS_NodeIterator >( shapeID, nbElemsToReturn, sm1stNode );
 }
 
-SMDS_ElemIteratorPtr SMDS_Mesh::shapeElementsIterator(int shapeID, size_t nbElemsToReturn) const
+SMDS_ElemIteratorPtr SMDS_Mesh::shapeElementsIterator(int                     shapeID,
+                                                      size_t                  nbElemsToReturn,
+                                                      const SMDS_MeshElement* sm1stElem) const
 {
-  return myCellFactory->GetShapeIterator< SMDS_ElemIterator >( shapeID, nbElemsToReturn );
+  return myCellFactory->GetShapeIterator< SMDS_ElemIterator >( shapeID, nbElemsToReturn, sm1stElem );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1831,6 +1885,7 @@ void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *               elem,
     case SMDSAbs_All: // avoid compilation warning
     case SMDSAbs_NbElementTypes: break;
     }
+    removedElems.push_back( *it);
 
     myCellFactory->Free( static_cast< const SMDS_MeshCell*>( *it ));
 
@@ -2908,17 +2963,17 @@ void SMDS_Mesh::CompactMesh()
 {
   this->myCompactTime = this->myModifTime;
 
-  bool idsChange = ( myNodeFactory->CompactChangePointers() ||
-                     myCellFactory->CompactChangePointers() );
+  bool idsChange = HasNumerationHoles();
   if ( idsChange )
   {
     std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
     for ( ; holder != myElemHolders.end(); ++holder )
       (*holder)->beforeCompacting();
   }
+  int oldCellSize = myCellFactory->GetMaxID();
 
   // remove "holes" in SMDS numeration
-  std::vector<int> idNodesOldToNew, idCellsNewToOld;
+  std::vector<int> idNodesOldToNew, idCellsNewToOld, idCellsOldToNew;
   myNodeFactory->Compact( idNodesOldToNew );
   myCellFactory->Compact( idCellsNewToOld );
 
@@ -2927,10 +2982,22 @@ void SMDS_Mesh::CompactMesh()
   int newCellSize = myCellFactory->NbUsedElements();
   myGrid->compactGrid( idNodesOldToNew, newNodeSize, idCellsNewToOld, newCellSize );
 
+  if ( idsChange && !myElemHolders.empty() )
+  {
+    // idCellsNewToOld -> idCellsOldToNew
+    idCellsOldToNew.resize( oldCellSize, oldCellSize );
+    for ( size_t iNew = 0; iNew < idCellsNewToOld.size(); ++iNew )
+    {
+      if ( idCellsNewToOld[ iNew ] >= (int) idCellsOldToNew.size() )
+        idCellsOldToNew.resize( ( 1 + idCellsNewToOld[ iNew ]) * 1.5, oldCellSize );
+      idCellsOldToNew[ idCellsNewToOld[ iNew ]] = iNew;
+    }
+  }
+
   std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
   for ( ; holder != myElemHolders.end(); ++holder )
     if ( idsChange )
-      (*holder)->restoreElements( idNodesOldToNew, idCellsNewToOld );
+      (*holder)->restoreElements( idNodesOldToNew, idCellsOldToNew );
     else
       (*holder)->compact();
 
@@ -2956,6 +3023,7 @@ void SMDS_Mesh::Modified()
 {
   if (this->myModified)
   {
+    myGrid->Modified();
     this->myModifTime++;
     myModified = false;
   }
@@ -2972,6 +3040,13 @@ bool SMDS_Mesh::IsCompacted()
   return ( this->myCompactTime == this->myModifTime );
 }
 
+//! are there holes in elements or nodes numeration
+bool SMDS_Mesh::HasNumerationHoles()
+{
+  return ( myNodeFactory->CompactChangePointers() ||
+           myCellFactory->CompactChangePointers() );
+}
+
 void SMDS_Mesh::setNbShapes( size_t nbShapes )
 {
   myNodeFactory->SetNbShapes( nbShapes );