Salome HOME
bos #20256: [CEA 18523] Porting SMESH to int 64 bits
[modules/smesh.git] / src / SMESH / SMESH_ProxyMesh.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // File      : SMESH_ProxyMesh.cxx
20 // Created   : Thu Dec  2 12:32:53 2010
21 // Author    : Edward AGAPOV (eap)
22
23 #include "SMESH_ProxyMesh.hxx"
24
25 #include "SMDS_IteratorOnIterators.hxx"
26 #include "SMDS_SetIterator.hxx"
27 #include "SMESHDS_Mesh.hxx"
28 #include "SMESH_Mesh.hxx"
29 #include "SMESH_MesherHelper.hxx"
30
31 #include <TopTools_ListIteratorOfListOfShape.hxx>
32 #include <TopExp.hxx>
33 #include <TopTools_IndexedMapOfShape.hxx>
34
35 #include <boost/container/flat_set.hpp>
36 #include <boost/make_shared.hpp>
37
38 //================================================================================
39 /*!
40  * \brief Constructor; mesh must be set by a descendant class
41  */
42 //================================================================================
43
44 SMESH_ProxyMesh::SMESH_ProxyMesh():_mesh(0), _subContainer(0)
45 {
46 }
47 //================================================================================
48 /*!
49  * \brief Constructor
50  */
51 //================================================================================
52
53 SMESH_ProxyMesh::SMESH_ProxyMesh(const SMESH_Mesh& mesh)
54   : _mesh( &mesh ),
55     _subContainer( new SubMesh( GetMeshDS() ) )
56 {
57 }
58
59 //================================================================================
60 /*!
61  * \brief Make a proxy mesh from components. Components become empty
62  */
63 //================================================================================
64
65 SMESH_ProxyMesh::SMESH_ProxyMesh(std::vector<SMESH_ProxyMesh::Ptr>& components):
66   _mesh(0)
67 {
68   if ( components.empty() ) return;
69
70   for ( unsigned i = 0; i < components.size(); ++i )
71   {
72     SMESH_ProxyMesh* m = components[i].get();
73     if ( !m ) continue;
74
75     takeTmpElemsInMesh( m );
76
77     if ( !_mesh && m->_mesh ) setMesh( *( m->_mesh ));
78     if ( _allowedTypes.empty() ) _allowedTypes = m->_allowedTypes;
79
80     if ( _subMeshes.size() < m->_subMeshes.size() )
81       _subMeshes.resize( m->_subMeshes.size(), 0 );
82     for ( unsigned j = 0; j < m->_subMeshes.size(); ++j )
83     {
84       if ( !m->_subMeshes[j] ) continue;
85       if ( _subMeshes[j] )
86       {
87         // unite 2 sub-meshes
88         std::set< const SMDS_MeshElement * > elems( _subMeshes[j]->_elements.begin(),
89                                                     _subMeshes[j]->_elements.end());
90         elems.insert( m->_subMeshes[j]->_elements.begin(),
91                       m->_subMeshes[j]->_elements.end());
92         _subMeshes[j]->_elements.assign( elems.begin(), elems.end() );
93         m->_subMeshes[j]->_elements.clear();
94
95         if ( !_subMeshes[j]->_n2n )
96           _subMeshes[j]->_n2n = m->_subMeshes[j]->_n2n, m->_subMeshes[j]->_n2n = 0;
97
98         else if ( _subMeshes[j]->_n2n && m->_subMeshes[j]->_n2n )
99           _subMeshes[j]->_n2n->insert( m->_subMeshes[j]->_n2n->begin(),
100                                        m->_subMeshes[j]->_n2n->end());
101       }
102       else
103       {
104         _subMeshes[j] = m->_subMeshes[j];
105         m->_subMeshes[j] = 0;
106       }
107     }
108   }
109 }
110
111 //================================================================================
112 /*!
113  * \brief Destructor deletes proxy submeshes and tmp elements
114  */
115 //================================================================================
116
117 SMESH_ProxyMesh::~SMESH_ProxyMesh()
118 {
119   delete _subContainer;
120
121   for ( size_t i = 0; i < _subMeshes.size(); ++i )
122     delete _subMeshes[i];
123   _subMeshes.clear();
124
125   std::set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.begin();
126   for ( ; i != _elemsInMesh.end(); ++i )
127     GetMeshDS()->RemoveFreeElement( *i, 0 );
128   _elemsInMesh.clear();
129 }
130
131 //================================================================================
132 /*!
133  * \brief Set mesh
134  */
135 //================================================================================
136
137 void SMESH_ProxyMesh::setMesh(const SMESH_Mesh& mesh)
138 {
139   _mesh = &mesh;
140   if ( _mesh )
141     _subContainer = new SubMesh( GetMeshDS() );
142 }
143
144 //================================================================================
145 /*!
146  * \brief Returns index of a shape
147  */
148 //================================================================================
149
150 int SMESH_ProxyMesh::shapeIndex(const TopoDS_Shape& shape) const
151 {
152   return ( shape.IsNull() || !_mesh->HasShapeToMesh() ? 0 : GetMeshDS()->ShapeToIndex(shape));
153 }
154
155 //================================================================================
156 /*!
157  * \brief Create a SubMesh
158  *  \param [ino] index - shape index
159  *  \return SubMesh* - new SubMesh
160  */
161 //================================================================================
162
163 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::newSubmesh(int index) const
164 {
165   return new SubMesh( GetMeshDS(),index );
166 }
167
168 //================================================================================
169 /*!
170  * \brief Returns the submesh of a shape; it can be a proxy sub-mesh
171  */
172 //================================================================================
173
174 const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const TopoDS_Shape& shape) const
175 {
176   return GetSubMesh( shapeIndex( shape ));
177 }
178
179 //================================================================================
180 /*!
181  * \brief Return a sub-mesh by a shape ID; it can be a proxy sub-mesh
182  */
183 //================================================================================
184
185 const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const int shapeID) const
186 {
187   const SMESHDS_SubMesh* sm = 0;
188
189   if ( 0 < shapeID && shapeID < (int)_subMeshes.size() )
190     sm = _subMeshes[ shapeID ];
191   if ( !sm )
192     sm = GetMeshDS()->MeshElements( shapeID );
193
194   return sm;
195 }
196
197 //================================================================================
198 /*!
199  * \brief Returns the proxy sub-mesh of a shape; it can be NULL
200  */
201 //================================================================================
202
203 const SMESH_ProxyMesh::SubMesh*
204 SMESH_ProxyMesh::GetProxySubMesh(const TopoDS_Shape& shape) const
205 {
206   size_t i = shapeIndex(shape);
207   return i < _subMeshes.size() ? _subMeshes[i] : 0;
208 }
209
210 //================================================================================
211 /*!
212  * \brief Returns the proxy node of a node; the input node is returned if no proxy exists
213  */
214 //================================================================================
215
216 const SMDS_MeshNode* SMESH_ProxyMesh::GetProxyNode( const SMDS_MeshNode* node ) const
217 {
218   const SMDS_MeshNode* proxy = node;
219   if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
220   {
221     if ( const SubMesh* proxySM = findProxySubMesh( node->getshapeId() ))
222       proxy = proxySM->GetProxyNode( node );
223   }
224   else
225   {
226     TopoDS_Shape shape = SMESH_MesherHelper::GetSubShapeByNode( node, GetMeshDS());
227     TopTools_ListIteratorOfListOfShape ancIt;
228     if ( !shape.IsNull() ) ancIt.Initialize( _mesh->GetAncestors( shape ));
229     for ( ; ancIt.More() && proxy == node; ancIt.Next() )
230       if ( const SubMesh* proxySM = findProxySubMesh( shapeIndex(ancIt.Value())))
231         proxy = proxySM->GetProxyNode( node );
232   }
233   return proxy;
234 }
235
236 //================================================================================
237 /*!
238  * \brief Returns number of proxy sub-meshes
239  */
240 //================================================================================
241
242 int SMESH_ProxyMesh::NbProxySubMeshes() const
243 {
244   int nb = 0;
245   for ( size_t i = 0; i < _subMeshes.size(); ++i )
246     nb += bool( _subMeshes[i] );
247
248   return nb;
249 }
250
251 namespace
252 {
253   //================================================================================
254   /*!
255    * \brief Iterator filtering elements by type
256    */
257   //================================================================================
258
259   class TFilteringIterator : public SMDS_ElemIterator
260   {
261     SMDS_ElemIteratorPtr             _iter;
262     const SMDS_MeshElement *         _curElem;
263     std::vector< SMDSAbs_EntityType> _okTypes;
264   public:
265     TFilteringIterator( const std::vector< SMDSAbs_EntityType>& okTypes,
266                         const SMDS_ElemIteratorPtr&             elemIterator)
267       :_iter(elemIterator), _curElem(0), _okTypes(okTypes)
268     {
269       next();
270     }
271     virtual bool more()
272     {
273       return _curElem;
274     }
275     virtual const SMDS_MeshElement* next()
276     {
277       const SMDS_MeshElement* res = _curElem;
278       _curElem = 0;
279       while ( _iter->more() && !_curElem )
280       {
281         _curElem = _iter->next();
282         if ( find( _okTypes.begin(), _okTypes.end(), _curElem->GetEntityType()) == _okTypes.end())
283           _curElem = 0;
284       }
285       return res;
286     }
287   };
288
289   //================================================================================
290   /*!
291    * \brief Iterator returning unique elements from a vector and another iterator
292    */
293   //================================================================================
294
295   class TUniqueIterator : public SMDS_ElemIterator
296   {
297     typedef boost::container::flat_set< const SMDS_MeshElement* >                 TElemSet;
298     typedef SMDS_SetIterator< const SMDS_MeshElement*, TElemSet::const_iterator > TSetIterator;
299
300     TElemSet      _uniqueElems;
301     TSetIterator* _iterator;
302
303   public:
304     TUniqueIterator( const std::vector< const SMDS_MeshElement* >& elems,
305                      const SMDS_ElemIteratorPtr&                   elemIterator )
306       : _uniqueElems( elems.begin(), elems.end() )
307     {
308       if ( elemIterator )
309         while ( elemIterator->more() )
310           _uniqueElems.insert( elemIterator->next() );
311
312       _iterator = new TSetIterator( _uniqueElems.begin(), _uniqueElems.end() );
313     }
314     ~TUniqueIterator()
315     {
316       delete _iterator;
317     }
318     virtual bool more()
319     {
320       return _iterator->more();
321     }
322     virtual const SMDS_MeshElement* next()
323     {
324       return _iterator->next();
325     }
326   };
327
328   //================================================================================
329   /*!
330    * \brief Return iterator on 2 element iterators
331    */
332   //================================================================================
333
334   SMDS_ElemIteratorPtr iteratorOn2Iterators( SMDS_ElemIteratorPtr it1, SMDS_ElemIteratorPtr it2 )
335   {
336     std::vector< SMDS_ElemIteratorPtr > iters; iters.reserve(2);
337     if ( it1 ) iters.push_back( it1 );
338     if ( it2 ) iters.push_back( it2 );
339
340     typedef std::vector< SMDS_ElemIteratorPtr >                                 TElemIterVector;
341     typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
342     return SMDS_ElemIteratorPtr( new TItersIter( iters ));
343   }
344 }
345
346 //================================================================================
347 /*!
348  * \brief Returns iterator on all faces on the shape taking into account substitutions
349  */
350 //================================================================================
351
352 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces(const TopoDS_Shape& shape) const
353 {
354   if ( !_mesh->HasShapeToMesh() )
355     return SMDS_ElemIteratorPtr();
356
357   _subContainer->RemoveAllSubmeshes();
358
359   TopTools_IndexedMapOfShape FF;
360   TopExp::MapShapes( shape, TopAbs_FACE, FF );
361   for ( int i = 1; i <= FF.Extent(); ++i )
362     if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
363       _subContainer->AddSubMesh( sm );
364
365   return _subContainer->SMESHDS_SubMesh::GetElements();
366 }
367
368 //================================================================================
369 /*!
370  * \brief Returns iterator on all faces of the mesh taking into account substitutions
371  * To be used in case of mesh without shape
372  */
373 //================================================================================
374
375 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces() const
376 {
377   if ( _mesh->HasShapeToMesh() )
378     return SMDS_ElemIteratorPtr();
379
380   _subContainer->RemoveAllSubmeshes();
381   for ( unsigned i = 0; i < _subMeshes.size(); ++i )
382     if ( _subMeshes[i] )
383       _subContainer->AddSubMesh( _subMeshes[i] );
384
385   if ( _subContainer->NbSubMeshes() == 0 ) // no elements substituted
386     return GetMeshDS()->elementsIterator(SMDSAbs_Face);
387
388   // if _allowedTypes is empty, only elements from _subMeshes are returned,...
389   SMDS_ElemIteratorPtr proxyIter = _subContainer->SMESHDS_SubMesh::GetElements();
390   if ( _allowedTypes.empty() || NbFaces() == _mesh->NbFaces() )
391     return proxyIter;
392
393   // ... else elements filtered using allowedTypes are additionally returned
394   SMDS_ElemIteratorPtr facesIter = GetMeshDS()->elementsIterator(SMDSAbs_Face);
395   SMDS_ElemIteratorPtr filterIter( new TFilteringIterator( _allowedTypes, facesIter ));
396   return iteratorOn2Iterators( proxyIter, filterIter );
397 }
398
399 //================================================================================
400 /*!
401  * \brief Return total nb of faces taking into account substitutions
402  */
403 //================================================================================
404
405 smIdType SMESH_ProxyMesh::NbFaces() const
406 {
407   smIdType nb = 0;
408   if ( _mesh->HasShapeToMesh() )
409   {
410     TopTools_IndexedMapOfShape FF;
411     TopExp::MapShapes( _mesh->GetShapeToMesh(), TopAbs_FACE, FF );
412     for ( int i = 1; i <= FF.Extent(); ++i )
413       if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
414         nb += sm->NbElements();
415   }
416   else
417   {
418     if ( _subMeshes.empty() )
419       return GetMeshDS()->NbFaces();
420
421     for ( unsigned i = 0; i < _subMeshes.size(); ++i )
422       if ( _subMeshes[i] )
423         nb += _subMeshes[i]->NbElements();
424
425     // if _allowedTypes is empty, only elements from _subMeshes are returned,
426     // else elements filtered using allowedTypes are additionally returned
427     if ( !_allowedTypes.empty() )
428     {
429       for ( int t = SMDSEntity_Triangle; t <= SMDSEntity_Quad_Quadrangle; ++t )
430       {
431         bool allowed =
432           ( find( _allowedTypes.begin(), _allowedTypes.end(), t ) != _allowedTypes.end() );
433         if ( allowed )
434           nb += GetMeshDS()->GetMeshInfo().NbEntities( SMDSAbs_EntityType( t ));
435       }
436     }
437   }
438   return nb;
439 }
440
441 //================================================================================
442 /*!
443  * \brief Returns a proxy sub-mesh; it is created if not yet exists
444  */
445 //================================================================================
446
447 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(int index)
448 {
449   if ( int(_subMeshes.size()) <= index )
450     _subMeshes.resize( index+1, 0 );
451   if ( !_subMeshes[index] )
452     _subMeshes[index] = newSubmesh( index );
453   return _subMeshes[index];
454 }
455
456 //================================================================================
457 /*!
458  * \brief Returns a proxy sub-mesh; it is created if not yet exists
459  */
460 //================================================================================
461
462 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(const TopoDS_Shape& shape)
463 {
464   return getProxySubMesh( shapeIndex( shape ));
465 }
466
467 //================================================================================
468 /*!
469  * \brief Returns a proxy sub-mesh
470  */
471 //================================================================================
472
473 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::findProxySubMesh(int shapeIndex) const
474 {
475   return shapeIndex < int(_subMeshes.size()) ? _subMeshes[shapeIndex] : 0;
476 }
477
478 //================================================================================
479 /*!
480  * \brief Returns mesh DS
481  */
482 //================================================================================
483
484 SMESHDS_Mesh* SMESH_ProxyMesh::GetMeshDS() const
485 {
486   return (SMESHDS_Mesh*)( _mesh ? _mesh->GetMeshDS() : 0 );
487 }
488
489 //================================================================================
490 /*!
491  * \brief Move proxy sub-mesh from other proxy mesh to this, returns true if sub-mesh found
492  */
493 //================================================================================
494
495 bool SMESH_ProxyMesh::takeProxySubMesh( const TopoDS_Shape&   shape,
496                                              SMESH_ProxyMesh* proxyMesh )
497 {
498   if ( proxyMesh && proxyMesh->_mesh == _mesh )
499   {
500     int iS = shapeIndex( shape );
501     if ( SubMesh* sm = proxyMesh->findProxySubMesh( iS ))
502     {
503       if ( iS >= int(_subMeshes.size()) )
504         _subMeshes.resize( iS + 1, 0 );
505       _subMeshes[iS] = sm;
506       proxyMesh->_subMeshes[iS] = 0;
507       return true;
508     }
509   }
510   return false;
511 }
512
513 //================================================================================
514 /*!
515  * \brief Move tmp elements residing the _mesh from other proxy mesh to this
516  */
517 //================================================================================
518
519 void SMESH_ProxyMesh::takeTmpElemsInMesh( SMESH_ProxyMesh* proxyMesh )
520 {
521   if ( proxyMesh )
522   {
523     _elemsInMesh.insert( proxyMesh->_elemsInMesh.begin(),
524                          proxyMesh->_elemsInMesh.end());
525     proxyMesh->_elemsInMesh.clear();
526   }
527 }
528
529 //================================================================================
530 /*!
531  * \brief Removes tmp elements from the _mesh
532  */
533 //================================================================================
534
535 void SMESH_ProxyMesh::removeTmpElement( const SMDS_MeshElement* elem )
536 {
537   if ( elem && elem->GetID() > 0 )
538   {
539     std::set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.find( elem );
540     if ( i != _elemsInMesh.end() )
541     {
542       std::vector< const SMDS_MeshNode* > nodes( elem->begin_nodes(), elem->end_nodes() );
543
544       GetMeshDS()->RemoveFreeElement( elem, 0 );
545       _elemsInMesh.erase( i );
546
547       for ( size_t i = 0; i < nodes.size(); ++i )
548         if ( nodes[i]->GetID() > 0 && nodes[i]->NbInverseElements() == 0 )
549           GetMeshDS()->RemoveFreeNode( nodes[i], 0, false );
550     }
551   }
552   else
553   {
554     delete elem;
555   }
556 }
557
558 //================================================================================
559 /*!
560  * \brief Stores tmp element residing the _mesh
561  */
562 //================================================================================
563
564 void SMESH_ProxyMesh::storeTmpElement( const SMDS_MeshElement* elem )
565 {
566   _elemsInMesh.insert( elem );
567 }
568
569 //================================================================================
570 /*!
571  * \brief Set node-node correspondence
572  */
573 //================================================================================
574
575 void SMESH_ProxyMesh::setNode2Node(const SMDS_MeshNode* srcNode,
576                                    const SMDS_MeshNode* proxyNode,
577                                    const SubMesh*       subMesh)
578 {
579   SubMesh* sm = const_cast<SubMesh*>( subMesh );
580   if ( !subMesh->_n2n )
581     sm->_n2n = new TN2NMap;
582   sm->_n2n->insert( std::make_pair( srcNode, proxyNode ));
583 }
584
585 //================================================================================
586 /*!
587  * \brief Return true if the element is a temporary one
588  */
589 //================================================================================
590
591 bool SMESH_ProxyMesh::IsTemporary(const SMDS_MeshElement* elem ) const
592 {
593   return ( elem->GetID() < 1 ) || _elemsInMesh.count( elem );
594 }
595
596 //================================================================================
597 /*!
598  * \brief Return iterator on inverse elements of a node that may be a proxy one
599  */
600 //================================================================================
601
602 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetInverseElementIterator(const SMDS_MeshNode* node,
603                                                                 SMDSAbs_ElementType  type) const
604 {
605   typedef std::vector< const SMDS_MeshElement* > TElemVec;
606   TElemVec *elemVecPtr;
607
608   TNodeElemVecMap& inverseElements = const_cast< TNodeElemVecMap& >( _inverseElements );
609   if ( inverseElements.IsEmpty() && NbProxySubMeshes() > 0 )
610   {
611     TElemVec elemVec;
612     for ( size_t i = 0; i < _subMeshes.size(); ++i )
613       if ( _subMeshes[i] )
614         for ( size_t j = 0; j < _subMeshes[i]->_elements.size(); ++j )
615         {
616           const SMDS_MeshElement* e = _subMeshes[i]->_elements[j];
617           for ( SMDS_NodeIteratorPtr nIt = e->nodeIterator(); nIt->more(); )
618           {
619             const SMDS_MeshNode* n = nIt->next();
620             elemVecPtr = inverseElements.ChangeSeek( n );
621             if ( !elemVecPtr )
622               elemVecPtr = inverseElements.Bound( n, elemVec );
623             elemVecPtr->push_back( e );
624           }
625         }
626   }
627
628   SMDS_ElemIteratorPtr iter = node->GetInverseElementIterator( type );
629
630   if (( elemVecPtr = inverseElements.ChangeSeek( node )))
631   {
632     if ( iter->more() )
633       iter = boost::make_shared< TUniqueIterator >( *elemVecPtr, iter );
634     else
635       iter = boost::make_shared< SMDS_ElementVectorIterator> ( elemVecPtr->begin(),
636                                                                elemVecPtr->end() );
637   }
638
639   return iter;
640 }
641
642 //================================================================================
643 /*!
644  * \brief Check if a FACE has prisms on its both sides
645  *  \param [in] smFace - sub-mesh of the FACE. NOT a proxy sub-mesh!
646  *  \return bool - true if there are prisms on the two sides
647  */
648 //================================================================================
649
650 bool SMESH_ProxyMesh::HasPrismsOnTwoSides( SMESHDS_SubMesh* smFace )
651 {
652   if ( !smFace || smFace->NbElements() == 0 )
653     return false;
654
655   SMDS_ElemIteratorPtr faces = smFace->GetElements();
656   while ( faces->more() )
657   {
658     const SMDS_MeshElement* f = faces->next();
659     std::vector<const SMDS_MeshNode*> fNodes( f->begin_nodes(), f->end_nodes() );
660     std::vector<const SMDS_MeshElement*> vols;
661     if ( SMDS_Mesh::GetElementsByNodes( fNodes, vols, SMDSAbs_Volume ) < 2 )
662       return false;
663     return ( vols[0]->NbCornerNodes() == 2 * f->NbCornerNodes() &&
664              vols[1]->NbCornerNodes() == 2 * f->NbCornerNodes() );
665   }
666   return false;
667 }
668
669 //================================================================================
670 /*!
671  * \brief SubMesh Constructor
672  */
673 //================================================================================
674
675 SMESH_ProxyMesh::SubMesh::SubMesh( const SMDS_Mesh* mesh, int index )
676   : SMESHDS_SubMesh( static_cast<const SMESHDS_Mesh*>( mesh ), index ),
677     _n2n(0)
678 {
679 }
680
681 //================================================================================
682 /*!
683  * \brief Return a proxy node or an input node
684  */
685 //================================================================================
686
687 const SMDS_MeshNode* SMESH_ProxyMesh::SubMesh::GetProxyNode( const SMDS_MeshNode* n ) const
688 {
689   TN2NMap::iterator n2n;
690   if ( _n2n && ( n2n = _n2n->find( n )) != _n2n->end())
691     return n2n->second;
692   return n;
693 }
694
695 //================================================================================
696 /*!
697  * \brief Deletes temporary elements
698  */
699 //================================================================================
700
701 void SMESH_ProxyMesh::SubMesh::Clear()
702 {
703   for ( unsigned i = 0; i < _elements.size(); ++i )
704     if ( _elements[i]->GetID() < 0 )
705       delete _elements[i];
706   _elements.clear();
707   if ( _n2n )
708     delete _n2n, _n2n = 0;
709 }
710
711 //================================================================================
712 /*!
713  * \brief Return number of elements in a proxy sub-mesh. The method is meaningful
714  *        for a sub-mesh containing tmp faces.
715  */
716 //================================================================================
717
718 smIdType SMESH_ProxyMesh::SubMesh::NbElements() const
719 {
720   return _uvPtStructVec.empty() ? _elements.size() : _uvPtStructVec.size() - 1;
721 }
722
723 //================================================================================
724 /*!
725  * \brief Return elements of a proxy sub-mesh. The method is meaningful
726  *        for a sub-mesh containing tmp faces.
727  */
728 //================================================================================
729
730 SMDS_ElemIteratorPtr SMESH_ProxyMesh::SubMesh::GetElements() const
731 {
732   return SMDS_ElemIteratorPtr
733     ( new SMDS_ElementVectorIterator( _elements.begin(), _elements.end() ));
734 }
735
736 //================================================================================
737 /*!
738  * \brief Return number of nodes in a proxy sub-mesh. The method is meaningful
739  *        for a sub-mesh containing nodes of 2D viscous layer.
740  */
741 //================================================================================
742
743 smIdType SMESH_ProxyMesh::SubMesh::NbNodes() const
744 {
745   return _uvPtStructVec.size();
746 }
747
748 //================================================================================
749 /*!
750  * \brief Return nodes of a proxy sub-mesh. The method is meaningful
751  *        for a sub-mesh containing nodes of 2D viscous layer.
752  */
753 //================================================================================
754
755 SMDS_NodeIteratorPtr SMESH_ProxyMesh::SubMesh::GetNodes() const
756 {
757   if ( !_uvPtStructVec.empty() )
758     return SMDS_NodeIteratorPtr ( new SMDS_SetIterator
759                                   < SMDS_pNode,
760                                   UVPtStructVec::const_iterator,
761                                   UVPtStruct::NodeAccessor >
762                                   ( _uvPtStructVec.begin(), _uvPtStructVec.end() ));
763
764   return SMDS_NodeIteratorPtr
765     ( new SMDS_SetIterator< SMDS_pNode, std::vector< SMDS_pElement >::const_iterator>
766       ( _elements.begin(), _elements.end() ));
767 }
768
769 //================================================================================
770 /*!
771  * \brief Store an element
772  */
773 //================================================================================
774
775 void SMESH_ProxyMesh::SubMesh::AddElement(const SMDS_MeshElement * e)
776 {
777   _elements.push_back( e );
778 }
779
780 //================================================================================
781 /*!
782  * \brief Check presence of element inside it-self
783  */
784 //================================================================================
785
786 bool SMESH_ProxyMesh::SubMesh::Contains(const SMDS_MeshElement * ME) const
787 {
788   if ( ME->GetType() != SMDSAbs_Node )
789     return find( _elements.begin(), _elements.end(), ME ) != _elements.end();
790   return false;
791 }