From 20cf4f072baae618adf4c89c65c0856eb58dbeb8 Mon Sep 17 00:00:00 2001 From: eap Date: Tue, 18 Jan 2011 11:01:28 +0000 Subject: [PATCH] 0020832: EDF 1359 SMESH : Automatic meshing of boundary layers + SMESH_ProxyMesh.hxx --- src/SMESH/Makefile.am | 7 +- src/SMESH/SMESH_ProxyMesh.cxx | 545 ++++++++++++++++++++++++++++++++++ src/SMESH/SMESH_ProxyMesh.hxx | 173 +++++++++++ 3 files changed, 722 insertions(+), 3 deletions(-) create mode 100644 src/SMESH/SMESH_ProxyMesh.cxx create mode 100644 src/SMESH/SMESH_ProxyMesh.hxx diff --git a/src/SMESH/Makefile.am b/src/SMESH/Makefile.am index 475436428..ac1138b49 100644 --- a/src/SMESH/Makefile.am +++ b/src/SMESH/Makefile.am @@ -22,7 +22,6 @@ # Author : Paul RASCLE, EDF # Modified by : Alexander BORODIN (OCN) - autotools usage # Module : SMESH -# $Header$ # include $(top_srcdir)/adm_local/unix/make_common_starter.am @@ -53,7 +52,8 @@ salomeinclude_HEADERS = \ SMESH_Comment.hxx \ SMESH_ComputeError.hxx \ SMESH_File.hxx \ - SMESH_SMESH.hxx + SMESH_SMESH.hxx \ + SMESH_ProxyMesh.hxx # Libraries targets @@ -78,7 +78,8 @@ dist_libSMESHimpl_la_SOURCES = \ SMESH_MesherHelper.cxx \ SMESH_Octree.cxx \ SMESH_OctreeNode.cxx \ - SMESH_File.cxx + SMESH_File.cxx \ + SMESH_ProxyMesh.cxx # additionnal information to compile and link file libSMESHimpl_la_CPPFLAGS = \ diff --git a/src/SMESH/SMESH_ProxyMesh.cxx b/src/SMESH/SMESH_ProxyMesh.cxx new file mode 100644 index 000000000..aba3c8e9c --- /dev/null +++ b/src/SMESH/SMESH_ProxyMesh.cxx @@ -0,0 +1,545 @@ +// Copyright (C) 2007-2010 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 +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : SMESH_ProxyMesh.cxx +// Created : Thu Dec 2 12:32:53 2010 +// Author : Edward AGAPOV (eap) + +#include "SMESH_ProxyMesh.hxx" + +#include "SMDS_IteratorOnIterators.hxx" +#include "SMDS_SetIterator.hxx" +#include "SMESH_MesherHelper.hxx" + +#include +#include +#include + +//================================================================================ +/*! + * \brief Constructor; mesh must be set by a descendant class + */ +//================================================================================ + +SMESH_ProxyMesh::SMESH_ProxyMesh():_mesh(0) +{ +} +//================================================================================ +/*! + * \brief Make a proxy mesh from components. Components become empty + */ +//================================================================================ + +SMESH_ProxyMesh::SMESH_ProxyMesh(vector& components): + _mesh(0) +{ + if ( components.empty() ) return; + + for ( unsigned i = 0; i < components.size(); ++i ) + { + SMESH_ProxyMesh* m = components[i].get(); + if ( !m ) continue; + + takeTmpElemsInMesh( m ); + + if ( !_mesh ) _mesh = m->_mesh; + if ( _allowedTypes.empty() ) _allowedTypes = m->_allowedTypes; + + if ( _subMeshes.size() < m->_subMeshes.size() ) + _subMeshes.resize( m->_subMeshes.size(), 0 ); + for ( unsigned j = 0; j < m->_subMeshes.size(); ++j ) + { + if ( !m->_subMeshes[j] ) continue; + if ( _subMeshes[j] ) + { + // unite 2 sub-meshes + set< const SMDS_MeshElement * > elems( _subMeshes[j]->_elements.begin(), + _subMeshes[j]->_elements.end()); + elems.insert( m->_subMeshes[j]->_elements.begin(), + m->_subMeshes[j]->_elements.end()); + _subMeshes[j]->_elements.assign( elems.begin(), elems.end() ); + m->_subMeshes[j]->_elements.clear(); + + if ( !_subMeshes[j]->_n2n ) + _subMeshes[j]->_n2n = m->_subMeshes[j]->_n2n, m->_subMeshes[j]->_n2n = 0; + + else if ( _subMeshes[j]->_n2n && m->_subMeshes[j]->_n2n ) + _subMeshes[j]->_n2n->insert( m->_subMeshes[j]->_n2n->begin(), + m->_subMeshes[j]->_n2n->end()); + } + else + { + _subMeshes[j] = m->_subMeshes[j]; + m->_subMeshes[j] = 0; + } + } + } +} + +//================================================================================ +/*! + * \brief Destructor deletes proxy submeshes and tmp elemens + */ +//================================================================================ + +SMESH_ProxyMesh::~SMESH_ProxyMesh() +{ + for ( unsigned i = 0; i < _subMeshes.size(); ++i ) + delete _subMeshes[i]; + _subMeshes.clear(); + + set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.begin(); + for ( ; i != _elemsInMesh.end(); ++i ) + GetMeshDS()->RemoveFreeElement( *i, 0 ); + _elemsInMesh.clear(); +} + +//================================================================================ +/*! + * \brief Returns index of a shape + */ +//================================================================================ + +int SMESH_ProxyMesh::shapeIndex(const TopoDS_Shape& shape) const +{ + return ( shape.IsNull() || !_mesh->HasShapeToMesh() ? 0 : GetMeshDS()->ShapeToIndex(shape)); +} + +//================================================================================ +/*! + * \brief Returns the submesh of a shape; it can be a proxy sub-mesh + */ +//================================================================================ + +const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const TopoDS_Shape& shape) const +{ + const SMESHDS_SubMesh* sm = 0; + + int i = shapeIndex(shape); + if ( i < _subMeshes.size() ) + sm = _subMeshes[i]; + if ( !sm ) + sm = GetMeshDS()->MeshElements( i ); + + return sm; +} + +//================================================================================ +/*! + * \brief Returns the proxy sub-mesh of a shape; it can be NULL + */ +//================================================================================ + +const SMESH_ProxyMesh::SubMesh* +SMESH_ProxyMesh::GetProxySubMesh(const TopoDS_Shape& shape) const +{ + int i = shapeIndex(shape); + return i < _subMeshes.size() ? _subMeshes[i] : 0; +} + +//================================================================================ +/*! + * \brief Returns the proxy node of a node; the input node is returned if no proxy exists + */ +//================================================================================ + +const SMDS_MeshNode* SMESH_ProxyMesh::GetProxyNode( const SMDS_MeshNode* node ) const +{ + const SMDS_MeshNode* proxy = node; + if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) + { + if ( const SubMesh* proxySM = findProxySubMesh( node->getshapeId() )) + proxy = proxySM->GetProxyNode( node ); + } + else + { + TopoDS_Shape shape = SMESH_MesherHelper::GetSubShapeByNode( node, GetMeshDS()); + TopTools_ListIteratorOfListOfShape ancIt; + if ( !shape.IsNull() ) ancIt.Initialize( _mesh->GetAncestors( shape )); + for ( ; ancIt.More() && proxy == node; ancIt.Next() ) + if ( const SubMesh* proxySM = findProxySubMesh( shapeIndex(ancIt.Value()))) + proxy = proxySM->GetProxyNode( node ); + } + return proxy; +} + +namespace +{ + //================================================================================ + /*! + * \brief Iterator filtering elements by type + */ + //================================================================================ + + class TFilteringIterator : public SMDS_ElemIterator + { + SMDS_ElemIteratorPtr _iter; + const SMDS_MeshElement * _curElem; + vector< SMDSAbs_EntityType> _okTypes; + public: + TFilteringIterator( const vector< SMDSAbs_EntityType>& okTypes, + const SMDS_ElemIteratorPtr& elemIterator) + :_iter(elemIterator), _curElem(0), _okTypes(okTypes) + { + next(); + } + virtual bool more() + { + return _curElem; + } + virtual const SMDS_MeshElement* next() + { + const SMDS_MeshElement* res = _curElem; + _curElem = 0; + while ( _iter->more() && !_curElem ) + { + _curElem = _iter->next(); + if ( find( _okTypes.begin(), _okTypes.end(), _curElem->GetEntityType()) == _okTypes.end()) + _curElem = 0; + } + return res; + } + }; +} + +//================================================================================ +/*! + * \brief Returns iterator on all faces on the shape taking into account substitutions + */ +//================================================================================ + +SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces(const TopoDS_Shape& shape) const +{ + if ( !_mesh->HasShapeToMesh() ) + return SMDS_ElemIteratorPtr(); + + _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 ); + + return _subContainer.SMESHDS_SubMesh::GetElements(); +} + +//================================================================================ +/*! + * \brief Returns iterator on all faces of the mesh taking into account substitutions + * To be used in case of mesh without shape + */ +//================================================================================ + +SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces() const +{ + if ( _mesh->HasShapeToMesh() ) + return SMDS_ElemIteratorPtr(); + + _subContainer.RemoveAllSubmeshes(); + for ( unsigned i = 0; i < _subMeshes.size(); ++i ) + if ( _subMeshes[i] ) + _subContainer.AddSubMesh( _subMeshes[i] ); + + 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(); + 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 )); + vector< SMDS_ElemIteratorPtr > iters(2); + iters[0] = proxyIter; + iters[1] = filterIter; + + typedef vector< SMDS_ElemIteratorPtr > TElemIterVector; + typedef SMDS_IteratorOnIterators TItersIter; + return SMDS_ElemIteratorPtr( new TItersIter( iters )); +} + +//================================================================================ +/*! + * \brief Return total nb of faces taking into account substitutions + */ +//================================================================================ + +int SMESH_ProxyMesh::NbFaces() const +{ + int nb = 0; + if ( _mesh->HasShapeToMesh() ) + { + TopTools_IndexedMapOfShape FF; + TopExp::MapShapes( _mesh->GetShapeToMesh(), TopAbs_FACE, FF ); + for ( int i = 1; i <= FF.Extent(); ++i ) + if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i))) + nb += sm->NbElements(); + } + else + { + if ( _subMeshes.empty() ) + return GetMeshDS()->NbFaces(); + + for ( unsigned i = 0; i < _subMeshes.size(); ++i ) + if ( _subMeshes[i] ) + nb += _subMeshes[i]->NbElements(); + + // if _allowedTypes is empty, only elements from _subMeshes are returned, + // else elements filtered using allowedTypes are additionally returned + if ( !_allowedTypes.empty() ) + { + for ( int t = SMDSEntity_Triangle; t <= SMDSEntity_Quad_Quadrangle; ++t ) + { + bool allowed = + ( find( _allowedTypes.begin(), _allowedTypes.end(), t ) != _allowedTypes.end() ); + if ( allowed ) + nb += GetMeshDS()->GetMeshInfo().NbEntities( SMDSAbs_EntityType( t )); + } + } + } + return nb; +} + +//================================================================================ +/*! + * \brief Returns a proxy sub-mesh; it is created if not yet exists + */ +//================================================================================ + +SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(int index) +{ + if ( int(_subMeshes.size()) <= index ) + _subMeshes.resize( index+1, 0 ); + if ( !_subMeshes[index] ) + _subMeshes[index] = new SubMesh( index ); + return _subMeshes[index]; +} + +//================================================================================ +/*! + * \brief Returns a proxy sub-mesh; it is created if not yet exists + */ +//================================================================================ + +SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(const TopoDS_Shape& shape) +{ + return getProxySubMesh( shapeIndex( shape )); +} + +//================================================================================ +/*! + * \brief Returns a proxy sub-mesh + */ +//================================================================================ + +SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::findProxySubMesh(int shapeIndex) const +{ + return shapeIndex < int(_subMeshes.size()) ? _subMeshes[shapeIndex] : 0; +} + +//================================================================================ +/*! + * \brief Returns mesh DS + */ +//================================================================================ + +SMESHDS_Mesh* SMESH_ProxyMesh::GetMeshDS() const +{ + return (SMESHDS_Mesh*)( _mesh ? _mesh->GetMeshDS() : 0 ); +} + +//================================================================================ +/*! + * \brief Move proxy sub-mesh from other proxy mesh to this, returns true if sub-mesh found + */ +//================================================================================ + +bool SMESH_ProxyMesh::takeProxySubMesh( const TopoDS_Shape& shape, + SMESH_ProxyMesh* proxyMesh ) +{ + if ( proxyMesh && proxyMesh->_mesh == _mesh ) + { + int iS = shapeIndex( shape ); + if ( SubMesh* sm = proxyMesh->findProxySubMesh( iS )) + { + if ( iS >= int(_subMeshes.size()) ) + _subMeshes.resize( iS + 1, 0 ); + _subMeshes[iS] = sm; + proxyMesh->_subMeshes[iS] = 0; + return true; + } + } + return false; +} + +//================================================================================ +/*! + * \brief Move tmp elements residing the _mesh from other proxy mesh to this + */ +//================================================================================ + +void SMESH_ProxyMesh::takeTmpElemsInMesh( SMESH_ProxyMesh* proxyMesh ) +{ + if ( proxyMesh ) + { + _elemsInMesh.insert( proxyMesh->_elemsInMesh.begin(), + proxyMesh->_elemsInMesh.end()); + proxyMesh->_elemsInMesh.clear(); + } +} + +//================================================================================ +/*! + * \brief Removes tmp faces from the _mesh + */ +//================================================================================ + +void SMESH_ProxyMesh::removeTmpElement( const SMDS_MeshElement* face ) +{ + if ( face && face->GetID() > 0 ) + { + set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.find( face ); + if ( i != _elemsInMesh.end() ) + { + GetMeshDS()->RemoveFreeElement( face, 0 ); + _elemsInMesh.erase( i ); + } + } + else + { + delete face; + } +} + +//================================================================================ +/*! + * \brief Stores tmp element residing the _mesh + */ +//================================================================================ + +void SMESH_ProxyMesh::storeTmpElement( const SMDS_MeshElement* face ) +{ + _elemsInMesh.insert( face ); +} + +//================================================================================ +/*! + * \brief Set node-node correspondence + */ +//================================================================================ + +void SMESH_ProxyMesh::setNode2Node(const SMDS_MeshNode* srcNode, + const SMDS_MeshNode* proxyNode, + const SubMesh* subMesh) +{ + SubMesh* sm = const_cast( subMesh ); + if ( !subMesh->_n2n ) + sm->_n2n = new TN2NMap; + sm->_n2n->insert( make_pair( srcNode, proxyNode )); +} + +//================================================================================ +/*! + * \brief Return true if the element is a temporary one + */ +//================================================================================ + +bool SMESH_ProxyMesh::IsTemporary(const SMDS_MeshElement* elem ) const +{ + return ( elem->GetID() < 1 ) || _elemsInMesh.count( elem ); +} + +//================================================================================ +/*! + * \brief Return a proxy node or an input node + */ +//================================================================================ + +const SMDS_MeshNode* SMESH_ProxyMesh::SubMesh::GetProxyNode( const SMDS_MeshNode* n ) const +{ + TN2NMap::iterator n2n; + if ( _n2n && ( n2n = _n2n->find( n )) != _n2n->end()) + return n2n->second; + return n; +} + +//================================================================================ +/*! + * \brief Deletes temporary elements + */ +//================================================================================ + +void SMESH_ProxyMesh::SubMesh::Clear() +{ + for ( unsigned i = 0; i < _elements.size(); ++i ) + if ( _elements[i]->GetID() < 0 ) + delete _elements[i]; + _elements.clear(); + if ( _n2n ) + delete _n2n, _n2n = 0; +} + +//================================================================================ +/*! + * \brief Return number of elements in a proxy submesh + */ +//================================================================================ + +int SMESH_ProxyMesh::SubMesh::NbElements() const +{ + return _elements.size(); +} + +//================================================================================ +/*! + * \brief Return elements of a proxy submesh + */ +//================================================================================ + +SMDS_ElemIteratorPtr SMESH_ProxyMesh::SubMesh::GetElements() const +{ + return SMDS_ElemIteratorPtr + ( new SMDS_ElementVectorIterator( _elements.begin(), _elements.end() )); +} + +//================================================================================ +/*! + * \brief Store an element + */ +//================================================================================ + +void SMESH_ProxyMesh::SubMesh::AddElement(const SMDS_MeshElement * e) +{ + _elements.push_back( e ); +} + +//================================================================================ +/*! + * \brief Check presence of element inside it-self + */ +//================================================================================ + +bool SMESH_ProxyMesh::SubMesh::Contains(const SMDS_MeshElement * ME) const +{ + if ( ME->GetType() != SMDSAbs_Node ) + return find( _elements.begin(), _elements.end(), ME ) != _elements.end(); + return false; +} diff --git a/src/SMESH/SMESH_ProxyMesh.hxx b/src/SMESH/SMESH_ProxyMesh.hxx new file mode 100644 index 000000000..3bcd18ded --- /dev/null +++ b/src/SMESH/SMESH_ProxyMesh.hxx @@ -0,0 +1,173 @@ +// Copyright (C) 2007-2010 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 +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SMESH_ProxyMesh.hxx +// Created : Thu Dec 2 10:05:35 2010 +// Author : Edward AGAPOV (eap) + +#ifndef __SMESH_ProxyMesh_HXX__ +#define __SMESH_ProxyMesh_HXX__ + +#include "SMESH_SMESH.hxx" + +#include "SMDS_MeshElement.hxx" +#include "SMESHDS_SubMesh.hxx" + +#include + +#include +#include +#include + +class SMDS_MeshNode; +class SMESHDS_Mesh; +class SMESH_Mesh; + +/*! + * \brief Container of mesh faces substituting other faces in the input mesh of 3D algorithm + */ +class SMESH_EXPORT SMESH_ProxyMesh +{ +public: + + typedef boost::shared_ptr Ptr; + + typedef std::map TN2NMap; + + //-------------------------------------------------------------------------------- + /*! + * \brief Proxy sub-mesh + */ + class SubMesh : public SMESHDS_SubMesh + { + public: + + const TN2NMap* GetNodeNodeMap() const { return _n2n; } + const SMDS_MeshNode* GetProxyNode( const SMDS_MeshNode* n ) const; + virtual void AddElement(const SMDS_MeshElement * e); + virtual int NbElements() const; + virtual SMDS_ElemIteratorPtr GetElements() const; + virtual void Clear(); + virtual bool Contains(const SMDS_MeshElement * ME) const; + + template< class ITERATOR > + void ChangeElements( ITERATOR it, ITERATOR end ) + { + // change SubMesh contents without deleting tmp faces + // for which the caller is responsible + _elements.clear(); + while ( it != end ) _elements.push_back( *it++ ); + } + SubMesh(int index=0):SMESHDS_SubMesh(0,index),_n2n(0) {} + ~SubMesh() { Clear(); } + + private: + std::vector _elements; + TN2NMap* _n2n; + friend class SMESH_ProxyMesh; + }; + //-------------------------------------------------------------------------------- + // Public interface + + SMESH_ProxyMesh(); + SMESH_ProxyMesh(std::vector& components); + SMESH_ProxyMesh(const SMESH_Mesh& mesh) { _mesh = &mesh; } + virtual ~SMESH_ProxyMesh(); + + // Returns the submesh of a face; it can be a proxy sub-mesh + const SMESHDS_SubMesh* GetSubMesh(const TopoDS_Shape& face) const; + + // Returns the proxy sub-mesh of a face; it can be NULL + const SubMesh* GetProxySubMesh(const TopoDS_Shape& face) const; + + // Returns the proxy node of a node; the input node is returned if no proxy exists + const SMDS_MeshNode* GetProxyNode( const SMDS_MeshNode* node ) const; + + // Returns iterator on all faces of the mesh taking into account substitutions + // To be used in case of mesh without shape + SMDS_ElemIteratorPtr GetFaces() const; + + // Returns iterator on all faces on the face taking into account substitutions + SMDS_ElemIteratorPtr GetFaces(const TopoDS_Shape& face) const; + + // Return total nb of faces taking into account substitutions + int NbFaces() const; + + bool IsTemporary(const SMDS_MeshElement* elem ) const; + + + + const SMESH_Mesh* GetMesh() const { return _mesh; } + + SMESHDS_Mesh* GetMeshDS() const; + + //-------------------------------------------------------------------------------- + // Interface for descendants + protected: + + void setMesh(const SMESH_Mesh& mesh) { _mesh = &mesh; } + + int shapeIndex(const TopoDS_Shape& shape) const; + + // returns a proxy sub-mesh; zero index is for the case of mesh w/o shape + SubMesh* findProxySubMesh(int shapeIndex=0) const; + + // returns a proxy sub-mesh; it is created if not yet exists + SubMesh* getProxySubMesh(int shapeIndex); + + // returns a proxy sub-mesh; it is created if not yet exists + SubMesh* getProxySubMesh(const TopoDS_Shape& shape=TopoDS_Shape()); + + // move proxy sub-mesh from other proxy mesh to this, returns true if sub-mesh found + bool takeProxySubMesh( const TopoDS_Shape& shape, SMESH_ProxyMesh* proxyMesh ); + + // move tmp elements residing the _mesh from other proxy mesh to this + void takeTmpElemsInMesh( SMESH_ProxyMesh* proxyMesh ); + + // removes tmp faces from the _mesh + void removeTmpElement( const SMDS_MeshElement* face ); + + // stores tmp element residing the _mesh + void storeTmpElement( const SMDS_MeshElement* face ); + + // store node-node correspondence + void setNode2Node(const SMDS_MeshNode* srcNode, + const SMDS_MeshNode* proxyNode, + const SubMesh* subMesh); + + // types of elements needed to implement NbFaces() and GetFaces(); + // if _allowedTypes is empty, only elements from _subMeshes are returned, + // else elements of _mesh filtered using allowedTypes are additionally returned + std::vector< SMDSAbs_EntityType> _allowedTypes; + + private: + + const SMESH_Mesh* _mesh; + + // proxy sub-meshes; index in vector == shapeIndex(shape) + std::vector< SubMesh* > _subMeshes; + + // tmp elements residing the _mesh, to be deleted at destruction + std::set< const SMDS_MeshElement* > _elemsInMesh; + + // Complex submesh used to iterate over elements in other sub-meshes + mutable SubMesh _subContainer; +}; + +#endif -- 2.39.2