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