Salome HOME
a4e4f5998b9c114fbddd472efb2cc778772b2290
[modules/smesh.git] / src / SMESH / SMESH_ProxyMesh.cxx
1 // Copyright (C) 2007-2012  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.
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 "SMESH_MesherHelper.hxx"
28
29 #include <TopTools_ListIteratorOfListOfShape.hxx>
30 #include <TopExp.hxx>
31 #include <TopTools_IndexedMapOfShape.hxx>
32
33 //================================================================================
34 /*!
35  * \brief Constructor; mesh must be set by a descendant class
36  */
37 //================================================================================
38
39 SMESH_ProxyMesh::SMESH_ProxyMesh():_mesh(0)
40 {
41 }
42 //================================================================================
43 /*!
44  * \brief Make a proxy mesh from components. Components become empty
45  */
46 //================================================================================
47
48 SMESH_ProxyMesh::SMESH_ProxyMesh(vector<SMESH_ProxyMesh::Ptr>& components):
49   _mesh(0)
50 {
51   if ( components.empty() ) return;
52
53   for ( unsigned i = 0; i < components.size(); ++i )
54   {
55     SMESH_ProxyMesh* m = components[i].get();
56     if ( !m ) continue;
57
58     takeTmpElemsInMesh( m );
59
60     if ( !_mesh ) _mesh = m->_mesh;
61     if ( _allowedTypes.empty() ) _allowedTypes = m->_allowedTypes;
62
63     if ( _subMeshes.size() < m->_subMeshes.size() )
64       _subMeshes.resize( m->_subMeshes.size(), 0 );
65     for ( unsigned j = 0; j < m->_subMeshes.size(); ++j )
66     {
67       if ( !m->_subMeshes[j] ) continue;
68       if ( _subMeshes[j] )
69       {
70         // unite 2 sub-meshes
71         set< const SMDS_MeshElement * > elems( _subMeshes[j]->_elements.begin(),
72                                                _subMeshes[j]->_elements.end());
73         elems.insert( m->_subMeshes[j]->_elements.begin(),
74                       m->_subMeshes[j]->_elements.end());
75         _subMeshes[j]->_elements.assign( elems.begin(), elems.end() );
76         m->_subMeshes[j]->_elements.clear();
77
78         if ( !_subMeshes[j]->_n2n )
79           _subMeshes[j]->_n2n = m->_subMeshes[j]->_n2n, m->_subMeshes[j]->_n2n = 0;
80
81         else if ( _subMeshes[j]->_n2n && m->_subMeshes[j]->_n2n )
82           _subMeshes[j]->_n2n->insert( m->_subMeshes[j]->_n2n->begin(),
83                                        m->_subMeshes[j]->_n2n->end());
84       }
85       else
86       {
87         _subMeshes[j] = m->_subMeshes[j];
88         m->_subMeshes[j] = 0;
89       }
90     }
91   }
92 }
93
94 //================================================================================
95 /*!
96  * \brief Destructor deletes proxy submeshes and tmp elemens
97  */
98 //================================================================================
99
100 SMESH_ProxyMesh::~SMESH_ProxyMesh()
101 {
102   for ( unsigned i = 0; i < _subMeshes.size(); ++i )
103     delete _subMeshes[i];
104   _subMeshes.clear();
105
106   set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.begin();
107   for ( ; i != _elemsInMesh.end(); ++i )
108     GetMeshDS()->RemoveFreeElement( *i, 0 );
109   _elemsInMesh.clear();
110 }
111
112 //================================================================================
113 /*!
114  * \brief Returns index of a shape
115  */
116 //================================================================================
117
118 int SMESH_ProxyMesh::shapeIndex(const TopoDS_Shape& shape) const
119 {
120   return ( shape.IsNull() || !_mesh->HasShapeToMesh() ? 0 : GetMeshDS()->ShapeToIndex(shape));
121 }
122
123 //================================================================================
124 /*!
125  * \brief Returns the submesh of a shape; it can be a proxy sub-mesh
126  */
127 //================================================================================
128
129 const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const TopoDS_Shape& shape) const
130 {
131   const SMESHDS_SubMesh* sm = 0;
132
133   int i = shapeIndex(shape);
134   if ( i < _subMeshes.size() )
135     sm = _subMeshes[i];
136   if ( !sm )
137     sm = GetMeshDS()->MeshElements( i );
138
139   return sm;
140 }
141
142 //================================================================================
143 /*!
144  * \brief Returns the proxy sub-mesh of a shape; it can be NULL
145  */
146 //================================================================================
147
148 const SMESH_ProxyMesh::SubMesh*
149 SMESH_ProxyMesh::GetProxySubMesh(const TopoDS_Shape& shape) const
150 {
151   int i = shapeIndex(shape);
152   return i < _subMeshes.size() ? _subMeshes[i] : 0;
153 }
154
155 //================================================================================
156 /*!
157  * \brief Returns the proxy node of a node; the input node is returned if no proxy exists
158  */
159 //================================================================================
160
161 const SMDS_MeshNode* SMESH_ProxyMesh::GetProxyNode( const SMDS_MeshNode* node ) const
162 {
163   const SMDS_MeshNode* proxy = node;
164   if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
165   {
166     if ( const SubMesh* proxySM = findProxySubMesh( node->getshapeId() ))
167       proxy = proxySM->GetProxyNode( node );
168   }
169   else
170   {
171     TopoDS_Shape shape = SMESH_MesherHelper::GetSubShapeByNode( node, GetMeshDS());
172     TopTools_ListIteratorOfListOfShape ancIt;
173     if ( !shape.IsNull() ) ancIt.Initialize( _mesh->GetAncestors( shape ));
174     for ( ; ancIt.More() && proxy == node; ancIt.Next() )
175       if ( const SubMesh* proxySM = findProxySubMesh( shapeIndex(ancIt.Value())))
176         proxy = proxySM->GetProxyNode( node );
177   }
178   return proxy;
179 }
180
181 namespace
182 {
183   //================================================================================
184   /*!
185    * \brief Iterator filtering elements by type
186    */
187   //================================================================================
188
189   class TFilteringIterator : public SMDS_ElemIterator
190   {
191     SMDS_ElemIteratorPtr        _iter;
192     const SMDS_MeshElement *    _curElem;
193     vector< SMDSAbs_EntityType> _okTypes;
194   public:
195     TFilteringIterator( const vector< SMDSAbs_EntityType>& okTypes,
196                         const SMDS_ElemIteratorPtr&        elemIterator)
197       :_iter(elemIterator), _curElem(0), _okTypes(okTypes)
198     {
199       next();
200     }
201     virtual bool more()
202     {
203       return _curElem;
204     }
205     virtual const SMDS_MeshElement* next()
206     {
207       const SMDS_MeshElement* res = _curElem;
208       _curElem = 0;
209       while ( _iter->more() && !_curElem )
210       {
211         _curElem = _iter->next();
212         if ( find( _okTypes.begin(), _okTypes.end(), _curElem->GetEntityType()) == _okTypes.end())
213           _curElem = 0;
214       }
215       return res;
216     }
217   };
218 }
219
220 //================================================================================
221 /*!
222  * \brief Returns iterator on all faces on the shape taking into account substitutions
223  */
224 //================================================================================
225
226 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces(const TopoDS_Shape& shape) const
227 {
228   if ( !_mesh->HasShapeToMesh() )
229     return SMDS_ElemIteratorPtr();
230
231   _subContainer.RemoveAllSubmeshes();
232
233   TopTools_IndexedMapOfShape FF;
234   TopExp::MapShapes( shape, TopAbs_FACE, FF );
235   for ( int i = 1; i <= FF.Extent(); ++i )
236     if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
237       _subContainer.AddSubMesh( sm );
238
239   return _subContainer.SMESHDS_SubMesh::GetElements();
240 }
241
242 //================================================================================
243 /*!
244  * \brief Returns iterator on all faces of the mesh taking into account substitutions
245  * To be used in case of mesh without shape
246  */
247 //================================================================================
248
249 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces() const
250 {
251   if ( _mesh->HasShapeToMesh() )
252     return SMDS_ElemIteratorPtr();
253
254   _subContainer.RemoveAllSubmeshes();
255   for ( unsigned i = 0; i < _subMeshes.size(); ++i )
256     if ( _subMeshes[i] )
257       _subContainer.AddSubMesh( _subMeshes[i] );
258
259   if ( _subContainer.NbSubMeshes() == 0 ) // no elements substituted
260     return GetMeshDS()->elementsIterator(SMDSAbs_Face);
261
262   // if _allowedTypes is empty, only elements from _subMeshes are returned,...
263   SMDS_ElemIteratorPtr proxyIter = _subContainer.SMESHDS_SubMesh::GetElements();
264   if ( _allowedTypes.empty() || NbFaces() == _mesh->NbFaces() )
265     return proxyIter;
266
267   // ... else elements filtered using allowedTypes are additionally returned
268   SMDS_ElemIteratorPtr facesIter = GetMeshDS()->elementsIterator(SMDSAbs_Face);
269   SMDS_ElemIteratorPtr filterIter( new TFilteringIterator( _allowedTypes, facesIter ));
270   vector< SMDS_ElemIteratorPtr > iters(2);
271   iters[0] = proxyIter;
272   iters[1] = filterIter;
273     
274   typedef vector< SMDS_ElemIteratorPtr > TElemIterVector;
275   typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
276   return SMDS_ElemIteratorPtr( new TItersIter( iters ));
277 }
278
279 //================================================================================
280 /*!
281  * \brief Return total nb of faces taking into account substitutions
282  */
283 //================================================================================
284
285 int SMESH_ProxyMesh::NbFaces() const
286 {
287   int nb = 0;
288   if ( _mesh->HasShapeToMesh() )
289   {
290     TopTools_IndexedMapOfShape FF;
291     TopExp::MapShapes( _mesh->GetShapeToMesh(), TopAbs_FACE, FF );
292     for ( int i = 1; i <= FF.Extent(); ++i )
293       if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
294         nb += sm->NbElements();
295   }
296   else
297   {
298     if ( _subMeshes.empty() )
299       return GetMeshDS()->NbFaces();
300
301     for ( unsigned i = 0; i < _subMeshes.size(); ++i )
302       if ( _subMeshes[i] )
303         nb += _subMeshes[i]->NbElements();
304
305     // if _allowedTypes is empty, only elements from _subMeshes are returned,
306     // else elements filtered using allowedTypes are additionally returned
307     if ( !_allowedTypes.empty() )
308     {
309       for ( int t = SMDSEntity_Triangle; t <= SMDSEntity_Quad_Quadrangle; ++t )
310       {
311         bool allowed =
312           ( find( _allowedTypes.begin(), _allowedTypes.end(), t ) != _allowedTypes.end() );
313         if ( allowed )
314           nb += GetMeshDS()->GetMeshInfo().NbEntities( SMDSAbs_EntityType( t ));
315       }
316     }
317   }
318   return nb;
319 }
320
321 //================================================================================
322 /*!
323  * \brief Returns a proxy sub-mesh; it is created if not yet exists
324  */
325 //================================================================================
326
327 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(int index)
328 {
329   if ( int(_subMeshes.size()) <= index )
330     _subMeshes.resize( index+1, 0 );
331   if ( !_subMeshes[index] )
332     _subMeshes[index] = new SubMesh( index );
333   return _subMeshes[index];
334 }
335
336 //================================================================================
337 /*!
338  * \brief Returns a proxy sub-mesh; it is created if not yet exists
339  */
340 //================================================================================
341
342 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(const TopoDS_Shape& shape)
343 {
344   return getProxySubMesh( shapeIndex( shape ));
345 }
346
347 //================================================================================
348 /*!
349  * \brief Returns a proxy sub-mesh
350  */
351 //================================================================================
352
353 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::findProxySubMesh(int shapeIndex) const
354 {
355   return shapeIndex < int(_subMeshes.size()) ? _subMeshes[shapeIndex] : 0;
356 }
357
358 //================================================================================
359 /*!
360  * \brief Returns mesh DS
361  */
362 //================================================================================
363
364 SMESHDS_Mesh* SMESH_ProxyMesh::GetMeshDS() const
365 {
366   return (SMESHDS_Mesh*)( _mesh ? _mesh->GetMeshDS() : 0 );
367 }
368
369 //================================================================================
370 /*!
371  * \brief Move proxy sub-mesh from other proxy mesh to this, returns true if sub-mesh found
372  */
373 //================================================================================
374
375 bool SMESH_ProxyMesh::takeProxySubMesh( const TopoDS_Shape&   shape,
376                                              SMESH_ProxyMesh* proxyMesh )
377 {
378   if ( proxyMesh && proxyMesh->_mesh == _mesh )
379   {
380     int iS = shapeIndex( shape );
381     if ( SubMesh* sm = proxyMesh->findProxySubMesh( iS ))
382     {
383       if ( iS >= int(_subMeshes.size()) )
384         _subMeshes.resize( iS + 1, 0 );
385       _subMeshes[iS] = sm;
386       proxyMesh->_subMeshes[iS] = 0;
387       return true;
388     }
389   }
390   return false;
391 }
392
393 //================================================================================
394 /*!
395  * \brief Move tmp elements residing the _mesh from other proxy mesh to this
396  */
397 //================================================================================
398
399 void SMESH_ProxyMesh::takeTmpElemsInMesh( SMESH_ProxyMesh* proxyMesh )
400 {
401   if ( proxyMesh )
402   {
403     _elemsInMesh.insert( proxyMesh->_elemsInMesh.begin(),
404                          proxyMesh->_elemsInMesh.end());
405     proxyMesh->_elemsInMesh.clear();
406   }
407 }
408
409 //================================================================================
410 /*!
411  * \brief Removes tmp faces from the _mesh
412  */
413 //================================================================================
414
415 void SMESH_ProxyMesh::removeTmpElement( const SMDS_MeshElement* face )
416 {
417   if ( face && face->GetID() > 0 )
418   {
419     set< const SMDS_MeshElement* >::iterator i =  _elemsInMesh.find( face );
420     if ( i != _elemsInMesh.end() )
421     {
422       GetMeshDS()->RemoveFreeElement( face, 0 );
423       _elemsInMesh.erase( i );
424     }
425   }
426   else
427   {
428     delete face;
429   }
430 }
431
432 //================================================================================
433 /*!
434  * \brief Stores tmp element residing the _mesh
435  */
436 //================================================================================
437
438 void SMESH_ProxyMesh::storeTmpElement( const SMDS_MeshElement* face )
439 {
440   _elemsInMesh.insert( face );
441 }
442
443 //================================================================================
444 /*!
445  * \brief Set node-node correspondence
446  */
447 //================================================================================
448
449 void SMESH_ProxyMesh::setNode2Node(const SMDS_MeshNode* srcNode,
450                                    const SMDS_MeshNode* proxyNode,
451                                    const SubMesh*       subMesh)
452 {
453   SubMesh* sm = const_cast<SubMesh*>( subMesh );
454   if ( !subMesh->_n2n )
455     sm->_n2n = new TN2NMap;
456   sm->_n2n->insert( make_pair( srcNode, proxyNode ));
457 }
458
459 //================================================================================
460 /*!
461  * \brief Return true if the element is a temporary one
462  */
463 //================================================================================
464
465 bool SMESH_ProxyMesh::IsTemporary(const SMDS_MeshElement* elem ) const
466 {
467   return ( elem->GetID() < 1 ) || _elemsInMesh.count( elem );
468 }
469
470 //================================================================================
471 /*!
472  * \brief Return a proxy node or an input node
473  */
474 //================================================================================
475
476 const SMDS_MeshNode* SMESH_ProxyMesh::SubMesh::GetProxyNode( const SMDS_MeshNode* n ) const
477 {
478   TN2NMap::iterator n2n;
479   if ( _n2n && ( n2n = _n2n->find( n )) != _n2n->end())
480     return n2n->second;
481   return n;
482 }
483
484 //================================================================================
485 /*!
486  * \brief Deletes temporary elements
487  */
488 //================================================================================
489
490 void SMESH_ProxyMesh::SubMesh::Clear()
491 {
492   for ( unsigned i = 0; i < _elements.size(); ++i )
493     if ( _elements[i]->GetID() < 0 )
494       delete _elements[i];
495   _elements.clear();
496   if ( _n2n )
497     delete _n2n, _n2n = 0;
498 }
499
500 //================================================================================
501 /*!
502  * \brief Return number of elements in a proxy submesh
503  */
504 //================================================================================
505
506 int SMESH_ProxyMesh::SubMesh::NbElements() const
507 {
508   return _elements.size();
509 }
510
511 //================================================================================
512 /*!
513  * \brief Return elements of a proxy submesh
514  */
515 //================================================================================
516
517 SMDS_ElemIteratorPtr SMESH_ProxyMesh::SubMesh::GetElements() const
518 {
519   return SMDS_ElemIteratorPtr
520     ( new SMDS_ElementVectorIterator( _elements.begin(), _elements.end() ));
521 }
522
523 //================================================================================
524 /*!
525  * \brief Store an element
526  */
527 //================================================================================
528
529 void SMESH_ProxyMesh::SubMesh::AddElement(const SMDS_MeshElement * e)
530 {
531   _elements.push_back( e );
532 }
533
534 //================================================================================
535 /*!
536  * \brief Check presence of element inside it-self
537  */
538 //================================================================================
539
540 bool SMESH_ProxyMesh::SubMesh::Contains(const SMDS_MeshElement * ME) const
541 {
542   if ( ME->GetType() != SMDSAbs_Node )
543     return find( _elements.begin(), _elements.end(), ME ) != _elements.end();
544   return false;
545 }