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