Salome HOME
Copyright update 2021
[modules/smesh.git] / src / SMESH / SMESH_ProxyMesh.cxx
index 0b4522d4aec6ea1522f3b00fc938e1eb0d7ebadb..ae7027860eea14db5c9ad706f37fb75fc2bea1e5 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
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 
 #include "SMDS_IteratorOnIterators.hxx"
 #include "SMDS_SetIterator.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESH_Mesh.hxx"
 #include "SMESH_MesherHelper.hxx"
 
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopExp.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
 
+#include <boost/container/flat_set.hpp>
+#include <boost/make_shared.hpp>
+
 //================================================================================
 /*!
  * \brief Constructor; mesh must be set by a descendant class
  */
 //================================================================================
 
-SMESH_ProxyMesh::SMESH_ProxyMesh():_mesh(0)
+SMESH_ProxyMesh::SMESH_ProxyMesh():_mesh(0), _subContainer(0)
+{
+}
+//================================================================================
+/*!
+ * \brief Constructor
+ */
+//================================================================================
+
+SMESH_ProxyMesh::SMESH_ProxyMesh(const SMESH_Mesh& mesh)
+  : _mesh( &mesh ),
+    _subContainer( new SubMesh( GetMeshDS() ) )
 {
 }
+
 //================================================================================
 /*!
  * \brief Make a proxy mesh from components. Components become empty
@@ -57,7 +74,7 @@ SMESH_ProxyMesh::SMESH_ProxyMesh(std::vector<SMESH_ProxyMesh::Ptr>& components):
 
     takeTmpElemsInMesh( m );
 
-    if ( !_mesh ) _mesh = m->_mesh;
+    if ( !_mesh && m->_mesh ) setMesh( *( m->_mesh ));
     if ( _allowedTypes.empty() ) _allowedTypes = m->_allowedTypes;
 
     if ( _subMeshes.size() < m->_subMeshes.size() )
@@ -93,13 +110,15 @@ SMESH_ProxyMesh::SMESH_ProxyMesh(std::vector<SMESH_ProxyMesh::Ptr>& components):
 
 //================================================================================
 /*!
- * \brief Destructor deletes proxy submeshes and tmp elemens
+ * \brief Destructor deletes proxy submeshes and tmp elements
  */
 //================================================================================
 
 SMESH_ProxyMesh::~SMESH_ProxyMesh()
 {
-  for ( unsigned i = 0; i < _subMeshes.size(); ++i )
+  delete _subContainer;
+
+  for ( size_t i = 0; i < _subMeshes.size(); ++i )
     delete _subMeshes[i];
   _subMeshes.clear();
 
@@ -109,6 +128,19 @@ SMESH_ProxyMesh::~SMESH_ProxyMesh()
   _elemsInMesh.clear();
 }
 
+//================================================================================
+/*!
+ * \brief Set mesh
+ */
+//================================================================================
+
+void SMESH_ProxyMesh::setMesh(const SMESH_Mesh& mesh)
+{
+  _mesh = &mesh;
+  if ( _mesh )
+    _subContainer = new SubMesh( GetMeshDS() );
+}
+
 //================================================================================
 /*!
  * \brief Returns index of a shape
@@ -120,6 +152,19 @@ int SMESH_ProxyMesh::shapeIndex(const TopoDS_Shape& shape) const
   return ( shape.IsNull() || !_mesh->HasShapeToMesh() ? 0 : GetMeshDS()->ShapeToIndex(shape));
 }
 
+//================================================================================
+/*!
+ * \brief Create a SubMesh
+ *  \param [ino] index - shape index
+ *  \return SubMesh* - new SubMesh
+ */
+//================================================================================
+
+SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::newSubmesh(int index) const
+{
+  return new SubMesh( GetMeshDS(),index );
+}
+
 //================================================================================
 /*!
  * \brief Returns the submesh of a shape; it can be a proxy sub-mesh
@@ -127,14 +172,24 @@ int SMESH_ProxyMesh::shapeIndex(const TopoDS_Shape& shape) const
 //================================================================================
 
 const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const TopoDS_Shape& shape) const
+{
+  return GetSubMesh( shapeIndex( shape ));
+}
+
+//================================================================================
+/*!
+ * \brief Return a sub-mesh by a shape ID; it can be a proxy sub-mesh
+ */
+//================================================================================
+
+const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const int shapeID) const
 {
   const SMESHDS_SubMesh* sm = 0;
 
-  size_t i = shapeIndex(shape);
-  if ( i < _subMeshes.size() )
-    sm = _subMeshes[i];
+  if ( 0 < shapeID && shapeID < (int)_subMeshes.size() )
+    sm = _subMeshes[ shapeID ];
   if ( !sm )
-    sm = GetMeshDS()->MeshElements( i );
+    sm = GetMeshDS()->MeshElements( shapeID );
 
   return sm;
 }
@@ -230,6 +285,62 @@ namespace
       return res;
     }
   };
+
+  //================================================================================
+  /*!
+   * \brief Iterator returning unique elements from a vector and another iterator
+   */
+  //================================================================================
+
+  class TUniqueIterator : public SMDS_ElemIterator
+  {
+    typedef boost::container::flat_set< const SMDS_MeshElement* >                 TElemSet;
+    typedef SMDS_SetIterator< const SMDS_MeshElement*, TElemSet::const_iterator > TSetIterator;
+
+    TElemSet      _uniqueElems;
+    TSetIterator* _iterator;
+
+  public:
+    TUniqueIterator( const std::vector< const SMDS_MeshElement* >& elems,
+                     const SMDS_ElemIteratorPtr&                   elemIterator )
+      : _uniqueElems( elems.begin(), elems.end() )
+    {
+      if ( elemIterator )
+        while ( elemIterator->more() )
+          _uniqueElems.insert( elemIterator->next() );
+
+      _iterator = new TSetIterator( _uniqueElems.begin(), _uniqueElems.end() );
+    }
+    ~TUniqueIterator()
+    {
+      delete _iterator;
+    }
+    virtual bool more()
+    {
+      return _iterator->more();
+    }
+    virtual const SMDS_MeshElement* next()
+    {
+      return _iterator->next();
+    }
+  };
+
+  //================================================================================
+  /*!
+   * \brief Return iterator on 2 element iterators
+   */
+  //================================================================================
+
+  SMDS_ElemIteratorPtr iteratorOn2Iterators( SMDS_ElemIteratorPtr it1, SMDS_ElemIteratorPtr it2 )
+  {
+    std::vector< SMDS_ElemIteratorPtr > iters; iters.reserve(2);
+    if ( it1 ) iters.push_back( it1 );
+    if ( it2 ) iters.push_back( it2 );
+
+    typedef std::vector< SMDS_ElemIteratorPtr >                                 TElemIterVector;
+    typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
+    return SMDS_ElemIteratorPtr( new TItersIter( iters ));
+  }
 }
 
 //================================================================================
@@ -243,15 +354,15 @@ SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces(const TopoDS_Shape& shape) const
   if ( !_mesh->HasShapeToMesh() )
     return SMDS_ElemIteratorPtr();
 
-  _subContainer.RemoveAllSubmeshes();
+  _subContainer->RemoveAllSubmeshes();
 
   TopTools_IndexedMapOfShape FF;
   TopExp::MapShapes( shape, TopAbs_FACE, FF );
   for ( int i = 1; i <= FF.Extent(); ++i )
     if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
-      _subContainer.AddSubMesh( sm );
+      _subContainer->AddSubMesh( sm );
 
-  return _subContainer.SMESHDS_SubMesh::GetElements();
+  return _subContainer->SMESHDS_SubMesh::GetElements();
 }
 
 //================================================================================
@@ -266,29 +377,23 @@ SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces() const
   if ( _mesh->HasShapeToMesh() )
     return SMDS_ElemIteratorPtr();
 
-  _subContainer.RemoveAllSubmeshes();
+  _subContainer->RemoveAllSubmeshes();
   for ( unsigned i = 0; i < _subMeshes.size(); ++i )
     if ( _subMeshes[i] )
-      _subContainer.AddSubMesh( _subMeshes[i] );
+      _subContainer->AddSubMesh( _subMeshes[i] );
 
-  if ( _subContainer.NbSubMeshes() == 0 ) // no elements substituted
+  if ( _subContainer->NbSubMeshes() == 0 ) // no elements substituted
     return GetMeshDS()->elementsIterator(SMDSAbs_Face);
 
   // if _allowedTypes is empty, only elements from _subMeshes are returned,...
-  SMDS_ElemIteratorPtr proxyIter = _subContainer.SMESHDS_SubMesh::GetElements();
+  SMDS_ElemIteratorPtr proxyIter = _subContainer->SMESHDS_SubMesh::GetElements();
   if ( _allowedTypes.empty() || NbFaces() == _mesh->NbFaces() )
     return proxyIter;
 
   // ... else elements filtered using allowedTypes are additionally returned
   SMDS_ElemIteratorPtr facesIter = GetMeshDS()->elementsIterator(SMDSAbs_Face);
   SMDS_ElemIteratorPtr filterIter( new TFilteringIterator( _allowedTypes, facesIter ));
-  std::vector< SMDS_ElemIteratorPtr > iters(2);
-  iters[0] = proxyIter;
-  iters[1] = filterIter;
-    
-  typedef std::vector< SMDS_ElemIteratorPtr >                                 TElemIterVector;
-  typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
-  return SMDS_ElemIteratorPtr( new TItersIter( iters ));
+  return iteratorOn2Iterators( proxyIter, filterIter );
 }
 
 //================================================================================
@@ -434,8 +539,14 @@ void SMESH_ProxyMesh::removeTmpElement( const SMDS_MeshElement* elem )
     std::set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.find( elem );
     if ( i != _elemsInMesh.end() )
     {
+      std::vector< const SMDS_MeshNode* > nodes( elem->begin_nodes(), elem->end_nodes() );
+
       GetMeshDS()->RemoveFreeElement( elem, 0 );
       _elemsInMesh.erase( i );
+
+      for ( size_t i = 0; i < nodes.size(); ++i )
+        if ( nodes[i]->GetID() > 0 && nodes[i]->NbInverseElements() == 0 )
+          GetMeshDS()->RemoveFreeNode( nodes[i], 0, false );
     }
   }
   else
@@ -482,6 +593,91 @@ bool SMESH_ProxyMesh::IsTemporary(const SMDS_MeshElement* elem ) const
   return ( elem->GetID() < 1 ) || _elemsInMesh.count( elem );
 }
 
+//================================================================================
+/*!
+ * \brief Return iterator on inverse elements of a node that may be a proxy one
+ */
+//================================================================================
+
+SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetInverseElementIterator(const SMDS_MeshNode* node,
+                                                                SMDSAbs_ElementType  type) const
+{
+  typedef std::vector< const SMDS_MeshElement* > TElemVec;
+  TElemVec *elemVecPtr;
+
+  TNodeElemVecMap& inverseElements = const_cast< TNodeElemVecMap& >( _inverseElements );
+  if ( inverseElements.IsEmpty() && NbProxySubMeshes() > 0 )
+  {
+    TElemVec elemVec;
+    for ( size_t i = 0; i < _subMeshes.size(); ++i )
+      if ( _subMeshes[i] )
+        for ( size_t j = 0; j < _subMeshes[i]->_elements.size(); ++j )
+        {
+          const SMDS_MeshElement* e = _subMeshes[i]->_elements[j];
+          for ( SMDS_NodeIteratorPtr nIt = e->nodeIterator(); nIt->more(); )
+          {
+            const SMDS_MeshNode* n = nIt->next();
+            elemVecPtr = inverseElements.ChangeSeek( n );
+            if ( !elemVecPtr )
+              elemVecPtr = inverseElements.Bound( n, elemVec );
+            elemVecPtr->push_back( e );
+          }
+        }
+  }
+
+  SMDS_ElemIteratorPtr iter = node->GetInverseElementIterator( type );
+
+  if (( elemVecPtr = inverseElements.ChangeSeek( node )))
+  {
+    if ( iter->more() )
+      iter = boost::make_shared< TUniqueIterator >( *elemVecPtr, iter );
+    else
+      iter = boost::make_shared< SMDS_ElementVectorIterator> ( elemVecPtr->begin(),
+                                                               elemVecPtr->end() );
+  }
+
+  return iter;
+}
+
+//================================================================================
+/*!
+ * \brief Check if a FACE has prisms on its both sides
+ *  \param [in] smFace - sub-mesh of the FACE. NOT a proxy sub-mesh!
+ *  \return bool - true if there are prisms on the two sides
+ */
+//================================================================================
+
+bool SMESH_ProxyMesh::HasPrismsOnTwoSides( SMESHDS_SubMesh* smFace )
+{
+  if ( !smFace || smFace->NbElements() == 0 )
+    return false;
+
+  SMDS_ElemIteratorPtr faces = smFace->GetElements();
+  while ( faces->more() )
+  {
+    const SMDS_MeshElement* f = faces->next();
+    std::vector<const SMDS_MeshNode*> fNodes( f->begin_nodes(), f->end_nodes() );
+    std::vector<const SMDS_MeshElement*> vols;
+    if ( SMDS_Mesh::GetElementsByNodes( fNodes, vols, SMDSAbs_Volume ) < 2 )
+      return false;
+    return ( vols[0]->NbCornerNodes() == 2 * f->NbCornerNodes() &&
+             vols[1]->NbCornerNodes() == 2 * f->NbCornerNodes() );
+  }
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief SubMesh Constructor
+ */
+//================================================================================
+
+SMESH_ProxyMesh::SubMesh::SubMesh( const SMDS_Mesh* mesh, int index )
+  : SMESHDS_SubMesh( static_cast<const SMESHDS_Mesh*>( mesh ), index ),
+    _n2n(0)
+{
+}
+
 //================================================================================
 /*!
  * \brief Return a proxy node or an input node