Salome HOME
Merge from V6_main 13/12/2012
[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 //================================================================================
182 /*!
183  * \brief Returns number of proxy sub-meshes
184  */
185 //================================================================================
186
187 int SMESH_ProxyMesh::NbProxySubMeshes() const
188 {
189   int nb = 0;
190   for ( size_t i = 0; i < _subMeshes.size(); ++i )
191     nb += bool( _subMeshes[i] );
192
193   return nb;
194 }
195
196 namespace
197 {
198   //================================================================================
199   /*!
200    * \brief Iterator filtering elements by type
201    */
202   //================================================================================
203
204   class TFilteringIterator : public SMDS_ElemIterator
205   {
206     SMDS_ElemIteratorPtr        _iter;
207     const SMDS_MeshElement *    _curElem;
208     vector< SMDSAbs_EntityType> _okTypes;
209   public:
210     TFilteringIterator( const vector< SMDSAbs_EntityType>& okTypes,
211                         const SMDS_ElemIteratorPtr&        elemIterator)
212       :_iter(elemIterator), _curElem(0), _okTypes(okTypes)
213     {
214       next();
215     }
216     virtual bool more()
217     {
218       return _curElem;
219     }
220     virtual const SMDS_MeshElement* next()
221     {
222       const SMDS_MeshElement* res = _curElem;
223       _curElem = 0;
224       while ( _iter->more() && !_curElem )
225       {
226         _curElem = _iter->next();
227         if ( find( _okTypes.begin(), _okTypes.end(), _curElem->GetEntityType()) == _okTypes.end())
228           _curElem = 0;
229       }
230       return res;
231     }
232   };
233 }
234
235 //================================================================================
236 /*!
237  * \brief Returns iterator on all faces on the shape taking into account substitutions
238  */
239 //================================================================================
240
241 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces(const TopoDS_Shape& shape) const
242 {
243   if ( !_mesh->HasShapeToMesh() )
244     return SMDS_ElemIteratorPtr();
245
246   _subContainer.RemoveAllSubmeshes();
247
248   TopTools_IndexedMapOfShape FF;
249   TopExp::MapShapes( shape, TopAbs_FACE, FF );
250   for ( int i = 1; i <= FF.Extent(); ++i )
251     if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
252       _subContainer.AddSubMesh( sm );
253
254   return _subContainer.SMESHDS_SubMesh::GetElements();
255 }
256
257 //================================================================================
258 /*!
259  * \brief Returns iterator on all faces of the mesh taking into account substitutions
260  * To be used in case of mesh without shape
261  */
262 //================================================================================
263
264 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces() const
265 {
266   if ( _mesh->HasShapeToMesh() )
267     return SMDS_ElemIteratorPtr();
268
269   _subContainer.RemoveAllSubmeshes();
270   for ( unsigned i = 0; i < _subMeshes.size(); ++i )
271     if ( _subMeshes[i] )
272       _subContainer.AddSubMesh( _subMeshes[i] );
273
274   if ( _subContainer.NbSubMeshes() == 0 ) // no elements substituted
275     return GetMeshDS()->elementsIterator(SMDSAbs_Face);
276
277   // if _allowedTypes is empty, only elements from _subMeshes are returned,...
278   SMDS_ElemIteratorPtr proxyIter = _subContainer.SMESHDS_SubMesh::GetElements();
279   if ( _allowedTypes.empty() || NbFaces() == _mesh->NbFaces() )
280     return proxyIter;
281
282   // ... else elements filtered using allowedTypes are additionally returned
283   SMDS_ElemIteratorPtr facesIter = GetMeshDS()->elementsIterator(SMDSAbs_Face);
284   SMDS_ElemIteratorPtr filterIter( new TFilteringIterator( _allowedTypes, facesIter ));
285   vector< SMDS_ElemIteratorPtr > iters(2);
286   iters[0] = proxyIter;
287   iters[1] = filterIter;
288     
289   typedef vector< SMDS_ElemIteratorPtr > TElemIterVector;
290   typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
291   return SMDS_ElemIteratorPtr( new TItersIter( iters ));
292 }
293
294 //================================================================================
295 /*!
296  * \brief Return total nb of faces taking into account substitutions
297  */
298 //================================================================================
299
300 int SMESH_ProxyMesh::NbFaces() const
301 {
302   int nb = 0;
303   if ( _mesh->HasShapeToMesh() )
304   {
305     TopTools_IndexedMapOfShape FF;
306     TopExp::MapShapes( _mesh->GetShapeToMesh(), TopAbs_FACE, FF );
307     for ( int i = 1; i <= FF.Extent(); ++i )
308       if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
309         nb += sm->NbElements();
310   }
311   else
312   {
313     if ( _subMeshes.empty() )
314       return GetMeshDS()->NbFaces();
315
316     for ( unsigned i = 0; i < _subMeshes.size(); ++i )
317       if ( _subMeshes[i] )
318         nb += _subMeshes[i]->NbElements();
319
320     // if _allowedTypes is empty, only elements from _subMeshes are returned,
321     // else elements filtered using allowedTypes are additionally returned
322     if ( !_allowedTypes.empty() )
323     {
324       for ( int t = SMDSEntity_Triangle; t <= SMDSEntity_Quad_Quadrangle; ++t )
325       {
326         bool allowed =
327           ( find( _allowedTypes.begin(), _allowedTypes.end(), t ) != _allowedTypes.end() );
328         if ( allowed )
329           nb += GetMeshDS()->GetMeshInfo().NbEntities( SMDSAbs_EntityType( t ));
330       }
331     }
332   }
333   return nb;
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(int index)
343 {
344   if ( int(_subMeshes.size()) <= index )
345     _subMeshes.resize( index+1, 0 );
346   if ( !_subMeshes[index] )
347     _subMeshes[index] = newSubmesh( index );
348   return _subMeshes[index];
349 }
350
351 //================================================================================
352 /*!
353  * \brief Returns a proxy sub-mesh; it is created if not yet exists
354  */
355 //================================================================================
356
357 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(const TopoDS_Shape& shape)
358 {
359   return getProxySubMesh( shapeIndex( shape ));
360 }
361
362 //================================================================================
363 /*!
364  * \brief Returns a proxy sub-mesh
365  */
366 //================================================================================
367
368 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::findProxySubMesh(int shapeIndex) const
369 {
370   return shapeIndex < int(_subMeshes.size()) ? _subMeshes[shapeIndex] : 0;
371 }
372
373 //================================================================================
374 /*!
375  * \brief Returns mesh DS
376  */
377 //================================================================================
378
379 SMESHDS_Mesh* SMESH_ProxyMesh::GetMeshDS() const
380 {
381   return (SMESHDS_Mesh*)( _mesh ? _mesh->GetMeshDS() : 0 );
382 }
383
384 //================================================================================
385 /*!
386  * \brief Move proxy sub-mesh from other proxy mesh to this, returns true if sub-mesh found
387  */
388 //================================================================================
389
390 bool SMESH_ProxyMesh::takeProxySubMesh( const TopoDS_Shape&   shape,
391                                              SMESH_ProxyMesh* proxyMesh )
392 {
393   if ( proxyMesh && proxyMesh->_mesh == _mesh )
394   {
395     int iS = shapeIndex( shape );
396     if ( SubMesh* sm = proxyMesh->findProxySubMesh( iS ))
397     {
398       if ( iS >= int(_subMeshes.size()) )
399         _subMeshes.resize( iS + 1, 0 );
400       _subMeshes[iS] = sm;
401       proxyMesh->_subMeshes[iS] = 0;
402       return true;
403     }
404   }
405   return false;
406 }
407
408 //================================================================================
409 /*!
410  * \brief Move tmp elements residing the _mesh from other proxy mesh to this
411  */
412 //================================================================================
413
414 void SMESH_ProxyMesh::takeTmpElemsInMesh( SMESH_ProxyMesh* proxyMesh )
415 {
416   if ( proxyMesh )
417   {
418     _elemsInMesh.insert( proxyMesh->_elemsInMesh.begin(),
419                          proxyMesh->_elemsInMesh.end());
420     proxyMesh->_elemsInMesh.clear();
421   }
422 }
423
424 //================================================================================
425 /*!
426  * \brief Removes tmp elements from the _mesh
427  */
428 //================================================================================
429
430 void SMESH_ProxyMesh::removeTmpElement( const SMDS_MeshElement* elem )
431 {
432   if ( elem && elem->GetID() > 0 )
433   {
434     set< const SMDS_MeshElement* >::iterator i =  _elemsInMesh.find( elem );
435     if ( i != _elemsInMesh.end() )
436     {
437       GetMeshDS()->RemoveFreeElement( elem, 0 );
438       _elemsInMesh.erase( i );
439     }
440   }
441   else
442   {
443     delete elem;
444   }
445 }
446
447 //================================================================================
448 /*!
449  * \brief Stores tmp element residing the _mesh
450  */
451 //================================================================================
452
453 void SMESH_ProxyMesh::storeTmpElement( const SMDS_MeshElement* elem )
454 {
455   _elemsInMesh.insert( elem );
456 }
457
458 //================================================================================
459 /*!
460  * \brief Set node-node correspondence
461  */
462 //================================================================================
463
464 void SMESH_ProxyMesh::setNode2Node(const SMDS_MeshNode* srcNode,
465                                    const SMDS_MeshNode* proxyNode,
466                                    const SubMesh*       subMesh)
467 {
468   SubMesh* sm = const_cast<SubMesh*>( subMesh );
469   if ( !subMesh->_n2n )
470     sm->_n2n = new TN2NMap;
471   sm->_n2n->insert( make_pair( srcNode, proxyNode ));
472 }
473
474 //================================================================================
475 /*!
476  * \brief Return true if the element is a temporary one
477  */
478 //================================================================================
479
480 bool SMESH_ProxyMesh::IsTemporary(const SMDS_MeshElement* elem ) const
481 {
482   return ( elem->GetID() < 1 ) || _elemsInMesh.count( elem );
483 }
484
485 //================================================================================
486 /*!
487  * \brief Return a proxy node or an input node
488  */
489 //================================================================================
490
491 const SMDS_MeshNode* SMESH_ProxyMesh::SubMesh::GetProxyNode( const SMDS_MeshNode* n ) const
492 {
493   TN2NMap::iterator n2n;
494   if ( _n2n && ( n2n = _n2n->find( n )) != _n2n->end())
495     return n2n->second;
496   return n;
497 }
498
499 //================================================================================
500 /*!
501  * \brief Deletes temporary elements
502  */
503 //================================================================================
504
505 void SMESH_ProxyMesh::SubMesh::Clear()
506 {
507   for ( unsigned i = 0; i < _elements.size(); ++i )
508     if ( _elements[i]->GetID() < 0 )
509       delete _elements[i];
510   _elements.clear();
511   if ( _n2n )
512     delete _n2n, _n2n = 0;
513 }
514
515 //================================================================================
516 /*!
517  * \brief Return number of elements in a proxy sub-mesh. The method is meaningful
518  *        for a sub-mesh containing tmp faces.
519  */
520 //================================================================================
521
522 int SMESH_ProxyMesh::SubMesh::NbElements() const
523 {
524   return _uvPtStructVec.empty() ? _elements.size() : _uvPtStructVec.size() - 1;
525 }
526
527 //================================================================================
528 /*!
529  * \brief Return elements of a proxy sub-mesh. The method is meaningful
530  *        for a sub-mesh containing tmp faces.
531  */
532 //================================================================================
533
534 SMDS_ElemIteratorPtr SMESH_ProxyMesh::SubMesh::GetElements() const
535 {
536   return SMDS_ElemIteratorPtr
537     ( new SMDS_ElementVectorIterator( _elements.begin(), _elements.end() ));
538 }
539
540 //================================================================================
541 /*!
542  * \brief Return number of nodes in a proxy sub-mesh. The method is meaningful
543  *        for a sub-mesh containing nodes of 2D viscous layer.
544  */
545 //================================================================================
546
547 int SMESH_ProxyMesh::SubMesh::NbNodes() const
548 {
549   return _uvPtStructVec.size();
550 }
551
552 //================================================================================
553 /*!
554  * \brief Return nodes of a proxy sub-mesh. The method is meaningful
555  *        for a sub-mesh containing nodes of 2D viscous layer.
556  */
557 //================================================================================
558
559 SMDS_NodeIteratorPtr SMESH_ProxyMesh::SubMesh::GetNodes() const
560 {
561   if ( !_uvPtStructVec.empty() )
562     return SMDS_NodeIteratorPtr ( new SMDS_SetIterator
563                                   < SMDS_pNode,
564                                   UVPtStructVec::const_iterator,
565                                   UVPtStruct::NodeAccessor >
566                                   ( _uvPtStructVec.begin(), _uvPtStructVec.end() ));
567
568   return SMDS_NodeIteratorPtr
569     ( new SMDS_SetIterator< SMDS_pNode, std::vector< SMDS_pElement >::const_iterator>
570       ( _elements.begin(), _elements.end() ));
571 }
572
573 //================================================================================
574 /*!
575  * \brief Store an element
576  */
577 //================================================================================
578
579 void SMESH_ProxyMesh::SubMesh::AddElement(const SMDS_MeshElement * e)
580 {
581   _elements.push_back( e );
582 }
583
584 //================================================================================
585 /*!
586  * \brief Check presence of element inside it-self
587  */
588 //================================================================================
589
590 bool SMESH_ProxyMesh::SubMesh::Contains(const SMDS_MeshElement * ME) const
591 {
592   if ( ME->GetType() != SMDSAbs_Node )
593     return find( _elements.begin(), _elements.end(), ME ) != _elements.end();
594   return false;
595 }