Salome HOME
23418: [OCC] Mesh: Minimization of memory usage of SMESH
[modules/smesh.git] / src / SMESHDS / SMESHDS_SubMesh.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SMESH SMESHDS : management of mesh data and SMESH document
24 //  File   : SMESH_SubMesh.cxx
25 //  Author : Yves FRICAUD, OCC
26 //  Module : SMESH
27 //  $Header: 
28 //
29 #include "SMESHDS_SubMesh.hxx"
30
31 #include "SMESHDS_Mesh.hxx"
32 #include "SMDS_SetIterator.hxx"
33 #include "SMDS_ElementFactory.hxx"
34
35 #include <utilities.h>
36
37 //================================================================================
38 /*!
39  * \brief Constructor
40  */
41 //================================================================================
42
43 SMESHDS_SubMesh::SMESHDS_SubMesh(SMESHDS_Mesh *parent, int index)
44 {
45   myParent = parent;
46   myIndex = index;
47   myNbElements = 0;
48   myNbNodes = 0;
49 }
50
51 //================================================================================
52 /*!
53  * \brief Destructor
54  */
55 //================================================================================
56
57 SMESHDS_SubMesh::~SMESHDS_SubMesh()
58 {
59 }
60
61 //=======================================================================
62 //function : AddElement
63 //purpose  :
64 //=======================================================================
65
66 void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * elem)
67 {
68   if (!IsComplexSubmesh())
69   {
70     if ( elem->GetType() == SMDSAbs_Node )
71     {
72       AddNode( static_cast< const SMDS_MeshNode* >( elem ));
73       return;
74     }
75     int oldShapeId = elem->GetShapeID();
76     if ( oldShapeId > 0 )
77     {
78       if (oldShapeId != myIndex)
79       {
80         throw SALOME_Exception
81           (LOCALIZED("add element in subshape already belonging to a subshape"));
82       }
83     }
84
85     elem->setShapeID( myIndex );
86     myNbElements++;
87   }
88 }
89
90 //=======================================================================
91 //function : RemoveElement
92 //purpose  :
93 //=======================================================================
94
95 bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * elem )
96 {
97   if ( !elem || elem->IsNull() || elem->getshapeId() != myIndex )
98   {
99     return false;
100   }
101   if ( !IsComplexSubmesh() )
102   {
103     elem->setShapeID( 0 );
104     myNbElements--;
105     return true;
106   }
107   return false;
108 }
109
110 //=======================================================================
111 //function : AddNode
112 //purpose  :
113 //=======================================================================
114
115 void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
116 {
117   if ( !IsComplexSubmesh() )
118   {
119     const int shapeId = N->getshapeId();
120     if ( shapeId > 0 )
121     {
122       if ( shapeId != myIndex )
123         throw SALOME_Exception
124           (LOCALIZED("a node being in sub-mesh is added to another sub-mesh"));
125       return; // already in
126     }
127     N->setShapeID( myIndex );
128     myNbNodes++;
129   }
130 }
131
132 //=======================================================================
133 //function : RemoveNode
134 //purpose  :
135 //=======================================================================
136
137 bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N)
138 {
139   if ( !N || N->getshapeId() != myIndex )
140   {
141     return false;
142   }
143   if ( !IsComplexSubmesh() )
144   {
145     N->setShapeID( 0 );
146     myNbNodes--;
147     return true;
148   }
149   return false;
150 }
151
152 //=======================================================================
153 //function : NbElements
154 //purpose  :
155 //=======================================================================
156
157 int SMESHDS_SubMesh::NbElements() const
158 {
159   if ( !IsComplexSubmesh() )
160     return myNbElements;
161
162   int nbElems = 0;
163   TSubMeshSet::const_iterator it = mySubMeshes.begin();
164   for ( ; it != mySubMeshes.end(); it++ )
165     nbElems += (*it)->NbElements();
166
167   return nbElems;
168 }
169
170 //=======================================================================
171 //function : NbNodes
172 //purpose  :
173 //=======================================================================
174
175 int SMESHDS_SubMesh::NbNodes() const
176 {
177   if ( !IsComplexSubmesh() )
178     return myNbNodes;
179
180   int nbElems = 0;
181   TSubMeshSet::const_iterator it = mySubMeshes.begin();
182   for ( ; it != mySubMeshes.end(); it++ )
183     nbElems += (*it)->NbNodes();
184
185   return nbElems;
186 }
187
188 /*!
189  * Template class used for iteration on vector of elements which can resize
190  * during iteration. The iterator returns only elements present upon its creation.
191  */
192 template <class ELEM, typename TSET> class MySetIterator : public SMDS_Iterator<ELEM>
193 {
194 protected:
195   int _iCur, _iEnd, _iDelta;
196   const TSET& _table;
197 public:
198   MySetIterator(const TSET& table, bool reverse): _table( table )
199   {
200     if ( reverse )
201     {
202       _iCur = _table.size()-1;
203       _iEnd = -1;
204       _iDelta = -1;
205     }
206     else
207     {
208       _iCur = 0;
209       _iEnd = _table.size();
210       _iDelta = 1;
211     }
212     if ( more() && !_table[ _iCur ])
213       next();
214   }
215
216   virtual bool more()
217   {
218     return ( _iEnd - _iCur ) * _iDelta > 0;
219   }
220
221   virtual ELEM next()
222   {
223     ELEM e = more() ? _table[ _iCur ] : 0;
224     _iCur += _iDelta;
225     while ( more() && !_table[ _iCur ])
226       _iCur += _iDelta;
227     return e;
228   }
229 };
230
231 // =====================
232 // class MyIterator
233 // =====================
234
235 template<typename VALUE> class MyIterator : public SMDS_Iterator<VALUE>
236 {
237 public:
238   MyIterator (const TSubMeshSet& theSubMeshes)
239     : myMore(false), mySubIt( theSubMeshes.begin() ), mySubEnd( theSubMeshes.end() )
240   {}
241   bool more()
242   {
243     while (( !myElemIt.get() || !myElemIt->more() ) && mySubIt != mySubEnd)
244     {
245       myElemIt = getElements(*mySubIt);
246       mySubIt++;
247     }
248     myMore = myElemIt.get() && myElemIt->more();
249     return myMore;
250   }
251   VALUE next()
252   {
253     VALUE elem = 0;
254     if ( myMore )
255       elem = myElemIt->next();
256     return elem;
257   }
258 protected:
259   virtual boost::shared_ptr< SMDS_Iterator<VALUE> >
260   getElements(const SMESHDS_SubMesh*) const = 0;
261
262 private:
263   bool                                      myMore;
264   TSubMeshSet::const_iterator               mySubIt, mySubEnd;
265   boost::shared_ptr< SMDS_Iterator<VALUE> > myElemIt;
266 };
267
268 // =====================
269 // class MyElemIterator
270 // =====================
271
272 class MyElemIterator: public MyIterator<const SMDS_MeshElement*>
273 {
274 public:
275   MyElemIterator (const TSubMeshSet& theSubMeshes)
276     :MyIterator<const SMDS_MeshElement*>( theSubMeshes ) {}
277   SMDS_ElemIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
278   { return theSubMesh->GetElements(); }
279 };
280
281 // =====================
282 // class MyNodeIterator
283 // =====================
284
285 class MyNodeIterator: public MyIterator<const SMDS_MeshNode*>
286 {
287 public:
288   MyNodeIterator (const TSubMeshSet& theSubMeshes)
289     :MyIterator<const SMDS_MeshNode*>( theSubMeshes ) {}
290   SMDS_NodeIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
291   { return theSubMesh->GetNodes(); }
292 };
293
294 //=======================================================================
295 //function : GetElements
296 //purpose  :
297 //=======================================================================
298
299 SMDS_ElemIteratorPtr SMESHDS_SubMesh::GetElements() const
300 {
301   if ( IsComplexSubmesh() )
302     return SMDS_ElemIteratorPtr( new MyElemIterator( mySubMeshes ));
303
304   return myParent->shapeElementsIterator( myIndex, myNbElements );
305 }
306
307 //=======================================================================
308 //function : GetNodes
309 //purpose  :
310 //=======================================================================
311
312 SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const
313 {
314   if ( IsComplexSubmesh() )
315     return SMDS_NodeIteratorPtr( new MyNodeIterator( mySubMeshes ));
316
317   return myParent->shapeNodesIterator( myIndex, myNbNodes );
318 }
319
320 //=======================================================================
321 //function : Contains
322 //purpose  : check if elem or node is in
323 //=======================================================================
324
325 bool SMESHDS_SubMesh::Contains(const SMDS_MeshElement * ME) const
326 {
327   if ( !ME || ME->IsNull() )
328     return false;
329
330   if ( IsComplexSubmesh() )
331   {
332     TSubMeshSet::const_iterator aSubIt = mySubMeshes.begin();
333     for (; aSubIt != mySubMeshes.end(); aSubIt++)
334       if ((*aSubIt)->Contains(ME))
335         return true;
336     return false;
337   }
338   return ME->getshapeId() == myIndex;
339 }
340
341 //=======================================================================
342 //function : IsQuadratic
343 //purpose  : Return true if my 1st element is quadratic
344 //=======================================================================
345
346 bool SMESHDS_SubMesh::IsQuadratic() const
347 {
348   if ( IsComplexSubmesh() )
349   {
350     TSubMeshSet::const_iterator aSubIt = mySubMeshes.begin();
351     for (; aSubIt != mySubMeshes.end(); aSubIt++)
352       if ((*aSubIt)->IsQuadratic())
353         return true;
354     return false;
355   }
356
357   if ( myNbElements == 0 )
358     return false;
359
360   SMDS_ElemIteratorPtr it = GetElements();
361   return it->more() && it->next()->IsQuadratic();
362 }
363
364 //=======================================================================
365 //function : AddSubMesh
366 //purpose  :
367 //=======================================================================
368
369 void SMESHDS_SubMesh::AddSubMesh( const SMESHDS_SubMesh* theSubMesh )
370 {
371   ASSERT( theSubMesh );
372   mySubMeshes.insert( theSubMesh );
373 }
374
375 //=======================================================================
376 //function : RemoveSubMesh
377 //purpose  : 
378 //=======================================================================
379
380 bool SMESHDS_SubMesh::RemoveSubMesh( const SMESHDS_SubMesh* theSubMesh )
381 {
382   return mySubMeshes.erase( theSubMesh );
383 }
384
385 //=======================================================================
386 //function : RemoveAllSubmeshes
387 //purpose  : 
388 //=======================================================================
389
390 void SMESHDS_SubMesh::RemoveAllSubmeshes()
391 {
392   mySubMeshes.clear();
393 }
394
395 //=======================================================================
396 //function : ContainsSubMesh
397 //purpose  :
398 //=======================================================================
399
400 bool SMESHDS_SubMesh::ContainsSubMesh( const SMESHDS_SubMesh* theSubMesh ) const
401 {
402   return mySubMeshes.find( theSubMesh ) != mySubMeshes.end();
403 }
404
405 //=======================================================================
406 //function : GetSubMeshIterator
407 //purpose  :
408 //=======================================================================
409
410 SMESHDS_SubMeshIteratorPtr SMESHDS_SubMesh::GetSubMeshIterator() const
411 {
412   typedef SMDS_SetIterator< const SMESHDS_SubMesh*, TSubMeshSet::const_iterator > TIterator;
413   return boost::make_shared< TIterator >( mySubMeshes.begin(), mySubMeshes.end());
414 }
415
416 //=======================================================================
417 //function : Clear
418 //purpose  : remove the contents
419 //=======================================================================
420
421 void SMESHDS_SubMesh::Clear()
422 {
423   if ( myParent && myParent->NbNodes() > 0 )
424   {
425     if ( myNbElements > 0 )
426       for ( SMDS_ElemIteratorPtr it = GetElements(); it->more(); )
427       {
428         const SMDS_MeshElement * elem = it->next();
429         elem->setShapeID( 0 );
430       }
431     if ( myNbNodes > 0 )
432       for ( SMDS_NodeIteratorPtr it = GetNodes(); it->more(); )
433       {
434         const SMDS_MeshNode * elem = it->next();
435         elem->setShapeID( 0 );
436       }
437   }
438
439   myNbElements = 0;
440   myNbNodes = 0;
441   if ( NbSubMeshes() > 0 )
442   {
443     SMESHDS_SubMeshIteratorPtr sub = GetSubMeshIterator();
444     while ( sub->more() ) {
445       if ( SMESHDS_SubMesh* sm = (SMESHDS_SubMesh*) sub->next())
446         sm->Clear();
447     }
448   }
449 }