Salome HOME
52566]: TC7.5.0: Empty group of Balls at Diameter Equal to filter
[modules/smesh.git] / src / SMESHDS / SMESHDS_SubMesh.cxx
1 // Copyright (C) 2007-2014  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 #include "SMESHDS_Mesh.hxx"
31
32 #include "utilities.h"
33 #include "SMDS_SetIterator.hxx"
34 #include <iostream>
35 #include <cassert>
36
37 using namespace std;
38
39
40 //================================================================================
41 /*!
42  * \brief Constructor
43  */
44 //================================================================================
45
46 SMESHDS_SubMesh::SMESHDS_SubMesh(SMESHDS_Mesh *parent, int index)
47 {
48   myParent = parent;
49   myElements.clear();
50   myNodes.clear();
51   myIndex = index;
52   myUnusedIdNodes = 0;
53   myUnusedIdElements = 0;
54 }
55
56 //================================================================================
57 /*!
58  * \brief Destructor
59  */
60 //================================================================================
61
62 SMESHDS_SubMesh::~SMESHDS_SubMesh()
63 {
64 }
65
66 //=======================================================================
67 //function : AddElement
68 //purpose  : 
69 //=======================================================================
70
71 void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * ME)
72 {
73   if (!IsComplexSubmesh())
74     {
75       if ( ME->GetType() == SMDSAbs_Node )
76       {
77         AddNode( static_cast< const SMDS_MeshNode* >( ME ));
78         return;
79       }
80       int oldShapeId = ME->getshapeId();
81       if ( oldShapeId > 0 )
82         {
83           if (oldShapeId != myIndex)
84             {
85               MESSAGE("add element in subshape already belonging to another subshape "
86                 << ME->GetID() << " " << oldShapeId << " " << myIndex);
87               throw SALOME_Exception(LOCALIZED("add element in subshape already belonging to a subshape"));
88             }
89           else
90             {
91               int idInSubShape = ME->getIdInShape();
92               if (idInSubShape >= 0)
93                 {
94                   MESSAGE("add element in subshape already belonging to that subshape "
95                       << ME->GetID() << " " << oldShapeId << " " << idInSubShape);
96                   // check if ok: do nothing if ok
97                   if (idInSubShape >= myElements.size())
98                     {
99                       MESSAGE("out of bounds " << idInSubShape << " " << myElements.size());
100                       throw SALOME_Exception(LOCALIZED("out of bounds"));
101                     }
102                   if (ME != myElements[idInSubShape])
103                     {
104                       MESSAGE("not the same element");
105                       throw SALOME_Exception(LOCALIZED("not the same element"));
106                     }
107                   MESSAGE("already done, OK, nothing to do");
108                   return;
109                 }
110             }
111         }
112
113       SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
114       elem->setShapeId(myIndex);
115       elem->setIdInShape(myElements.size());
116       myElements.push_back(ME);
117     }
118 }
119
120 //=======================================================================
121 //function : RemoveElement
122 //purpose  : 
123 //=======================================================================
124
125 bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * ME, bool isElemDeleted)
126 {
127   if (!ME)
128   {
129     MESSAGE("-----------------> Remove Null Element " << isElemDeleted);
130     return false;
131   }
132   if (!IsComplexSubmesh())
133   {
134     if ( ME->getshapeId() != myIndex )
135       return false;
136     int idInSubShape = ME->getIdInShape();
137     SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
138     elem->setShapeId(0);
139     elem->setIdInShape(-1);
140     if ((idInSubShape >= 0) && (idInSubShape < myElements.size()))
141     {
142       myElements[idInSubShape] = 0; // this vector entry is no more used
143       if ( ++myUnusedIdElements == (int) myElements.size() )
144       {
145         clearVector( myElements );
146         myUnusedIdElements = 0;
147       }
148       return true;
149     }
150     return false;
151   }
152   MESSAGE("Try to remove an element from a complex submesh ");
153   return false;
154 }
155
156 //=======================================================================
157 //function : AddNode
158 //purpose  : 
159 //=======================================================================
160
161 void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
162 {
163   if ( !IsComplexSubmesh() )
164   {
165     const int idInSubShape = N->getIdInShape();
166     const int shapeId      = N->getshapeId();
167     if ((shapeId > 0) && (idInSubShape >= 0))
168     {
169       if ( shapeId != myIndex )
170         throw SALOME_Exception
171           (LOCALIZED("a node being in sub-mesh is added to another sub-mesh"));
172       if ( idInSubShape >= myNodes.size() || myNodes[ idInSubShape ] != N )
173         throw SALOME_Exception
174           (LOCALIZED("a node with wrong idInSubShape is re-added to the same sub-mesh"));
175       return; // already in
176     }
177     SMDS_MeshNode* node = (SMDS_MeshNode*)(N);
178     node->setShapeId(myIndex);
179     node->setIdInShape(myNodes.size());
180     myNodes.push_back(N);
181   }
182 }
183
184 //=======================================================================
185 //function : RemoveNode
186 //purpose  : 
187 //=======================================================================
188
189 bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N, bool isNodeDeleted)
190 {
191   if (!IsComplexSubmesh())
192   {
193     if ( N->getshapeId() != myIndex )
194       return false;
195     int idInSubShape = N->getIdInShape();
196     SMDS_MeshNode* node = (SMDS_MeshNode*) (N);
197     node->setShapeId(0);
198     node->setIdInShape(-1);
199     if ((idInSubShape >= 0) && (idInSubShape < myNodes.size()))
200     {
201       myNodes[idInSubShape] = 0; // this vector entry is no more used
202       if ( ++myUnusedIdNodes == (int) myNodes.size() )
203       {
204         clearVector( myNodes );
205         myUnusedIdNodes = 0;
206       }
207       return true;
208     }
209     return false;
210   }
211   MESSAGE("Try to remove a node from a complex submesh");
212   return false;
213 }
214
215 //=======================================================================
216 //function : NbElements
217 //purpose  : 
218 //=======================================================================
219
220 int SMESHDS_SubMesh::NbElements() const
221 {
222   if ( !IsComplexSubmesh() )
223     return myElements.size() - myUnusedIdElements;
224
225   int nbElems = 0;
226   set<const SMESHDS_SubMesh*>::const_iterator it = mySubMeshes.begin();
227   for ( ; it != mySubMeshes.end(); it++ )
228     nbElems += (*it)->NbElements();
229
230   return nbElems;
231 }
232
233 //=======================================================================
234 //function : NbNodes
235 //purpose  : 
236 //=======================================================================
237
238 int SMESHDS_SubMesh::NbNodes() const
239 {
240   if ( !IsComplexSubmesh() )
241     return myNodes.size() - myUnusedIdNodes;
242
243   int nbElems = 0;
244   set<const SMESHDS_SubMesh*>::const_iterator it = mySubMeshes.begin();
245   for ( ; it != mySubMeshes.end(); it++ )
246     nbElems += (*it)->NbNodes();
247
248   return nbElems;
249 }
250
251 /*!
252  * template class used for iteration on submesh elements. Interface of iterator remains
253  * unchanged after redesign of SMDS to avoid modification everywhere in SMESH.
254  * instances are stored in shared_ptr for automatic destruction.
255  * Container is copied for iteration, because original can be modified
256  * by addition of elements, for instance, and then reallocated (vector)
257  */
258 template <class ELEM, typename TSET> class MySetIterator : public SMDS_Iterator<ELEM>
259 {
260 protected:
261   typename TSET::const_iterator _it, _end;
262   TSET _table;
263 public:
264   MySetIterator(const TSET& table)
265   {
266     _table = table;
267     _it = _table.begin();
268     _end = _table.end();
269     while ((_it != _end) && (*_it == 0))
270       _it++;
271   }
272
273   virtual bool more()
274   {
275     while ((_it != _end) && (*_it == 0))
276       _it++;
277     return (_it != _end);
278   }
279
280   virtual ELEM next()
281   {
282     ELEM e = *_it;
283     _it++;
284     return e;
285   }
286 };
287
288 // =====================
289 // class MyIterator
290 // =====================
291
292 template<typename VALUE> class MyIterator : public SMDS_Iterator<VALUE>
293 {
294  public:
295   MyIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
296     : mySubIt( theSubMeshes.begin() ), mySubEnd( theSubMeshes.end() ), myMore(false)
297     {}
298   bool more()
299   {
300     while (( !myElemIt.get() || !myElemIt->more() ) && mySubIt != mySubEnd)
301     {
302       myElemIt = getElements(*mySubIt);
303       mySubIt++;
304     }
305     myMore = myElemIt.get() && myElemIt->more();
306     return myMore;
307   }
308   VALUE next()
309   {
310     VALUE elem = 0;
311     if ( myMore )
312       elem = myElemIt->next();
313     return elem;
314   }
315  protected:
316   virtual boost::shared_ptr< SMDS_Iterator<VALUE> >
317     getElements(const SMESHDS_SubMesh*) const = 0;
318
319  private:
320   bool                                        myMore;
321   set<const SMESHDS_SubMesh*>::const_iterator mySubIt, mySubEnd;
322   boost::shared_ptr< SMDS_Iterator<VALUE> >   myElemIt;
323 };
324
325 // =====================
326 // class MyElemIterator
327 // =====================
328
329 class MyElemIterator: public MyIterator<const SMDS_MeshElement*>
330 {
331  public:
332   MyElemIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
333     :MyIterator<const SMDS_MeshElement*>( theSubMeshes ) {}
334   SMDS_ElemIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
335   { return theSubMesh->GetElements(); }
336 };
337
338 // =====================
339 // class MyNodeIterator
340 // =====================
341
342 class MyNodeIterator: public MyIterator<const SMDS_MeshNode*>
343 {
344  public:
345   MyNodeIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
346     :MyIterator<const SMDS_MeshNode*>( theSubMeshes ) {}
347   SMDS_NodeIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
348   { return theSubMesh->GetNodes(); }
349 };
350   
351 //=======================================================================
352 //function : GetElements
353 //purpose  : 
354 //=======================================================================
355
356 SMDS_ElemIteratorPtr SMESHDS_SubMesh::GetElements() const
357 {
358   if ( IsComplexSubmesh() )
359     return SMDS_ElemIteratorPtr( new MyElemIterator( mySubMeshes ));
360   return SMDS_ElemIteratorPtr(new MySetIterator<const SMDS_MeshElement*, std::vector<const SMDS_MeshElement*> >(myElements));
361 }
362
363 //=======================================================================
364 //function : GetNodes
365 //purpose  : 
366 //=======================================================================
367
368 SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const
369 {
370   if ( IsComplexSubmesh() )
371     return SMDS_NodeIteratorPtr( new MyNodeIterator( mySubMeshes ));
372
373   return SMDS_NodeIteratorPtr(new MySetIterator<const SMDS_MeshNode*, std::vector<const SMDS_MeshNode*> >(myNodes));
374 }
375
376 //=======================================================================
377 //function : Contains
378 //purpose  : check if elem or node is in
379 //=======================================================================
380
381 bool SMESHDS_SubMesh::Contains(const SMDS_MeshElement * ME) const
382 {
383   // DO NOT TRY TO FIND A REMOVED ELEMENT !!
384   //if ( IsComplexSubmesh() || !ME )
385   if (!ME)
386     return false;
387
388   if (IsComplexSubmesh())
389     {
390       set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
391       for (; aSubIt != mySubMeshes.end(); aSubIt++)
392         if ((*aSubIt)->Contains(ME))
393           return true;
394       return false;
395     }
396
397   if (ME->GetType() == SMDSAbs_Node)
398     {
399       int idInShape = ME->getIdInShape();
400       if ((idInShape >= 0) && (idInShape < myNodes.size()))
401         if (myNodes[idInShape] == ME)
402           return true;
403     }
404   else
405     {
406       int idInShape = ME->getIdInShape();
407       if ((idInShape >= 0) && (idInShape < myElements.size()))
408         if (myElements[idInShape] == ME)
409           return true;
410     }
411   return false;
412 }
413
414 //=======================================================================
415 //function : AddSubMesh
416 //purpose  : 
417 //=======================================================================
418
419 void SMESHDS_SubMesh::AddSubMesh( const SMESHDS_SubMesh* theSubMesh )
420 {
421   ASSERT( theSubMesh );
422   mySubMeshes.insert( theSubMesh );
423 }
424
425 //=======================================================================
426 //function : RemoveSubMesh
427 //purpose  : 
428 //=======================================================================
429
430 bool SMESHDS_SubMesh::RemoveSubMesh( const SMESHDS_SubMesh* theSubMesh )
431 {
432   return mySubMeshes.erase( theSubMesh );
433 }
434
435 //=======================================================================
436 //function : RemoveAllSubmeshes
437 //purpose  : 
438 //=======================================================================
439
440 void SMESHDS_SubMesh::RemoveAllSubmeshes()
441 {
442   mySubMeshes.clear();
443 }
444
445 //=======================================================================
446 //function : ContainsSubMesh
447 //purpose  : 
448 //=======================================================================
449
450 bool SMESHDS_SubMesh::ContainsSubMesh( const SMESHDS_SubMesh* theSubMesh ) const
451 {
452   return mySubMeshes.find( theSubMesh ) != mySubMeshes.end();
453 }
454
455 //=======================================================================
456 //function : GetSubMeshIterator
457 //purpose  : 
458 //=======================================================================
459
460 SMESHDS_SubMeshIteratorPtr SMESHDS_SubMesh::GetSubMeshIterator() const
461 {
462   typedef set<const SMESHDS_SubMesh*>::const_iterator TIterator;
463   return SMESHDS_SubMeshIteratorPtr
464     ( new SMDS_SetIterator< const SMESHDS_SubMesh*, TIterator >( mySubMeshes.begin(),
465                                                                  mySubMeshes.end()));
466 }
467
468 //=======================================================================
469 //function : Clear
470 //purpose  : remove the contents
471 //=======================================================================
472
473 void SMESHDS_SubMesh::Clear()
474 {
475   clearVector( myElements );
476   clearVector( myNodes );
477   myUnusedIdNodes = 0;
478   myUnusedIdElements = 0;
479   if ( NbSubMeshes() > 0 )
480   {
481     SMESHDS_SubMeshIteratorPtr sub = GetSubMeshIterator();
482     while ( sub->more() ) {
483       if ( SMESHDS_SubMesh* sm = (SMESHDS_SubMesh*) sub->next())
484         sm->Clear();
485     }
486   }
487 }
488
489 int SMESHDS_SubMesh::getSize()
490 {
491   int c = NbNodes();
492   int d = NbElements();
493   return c+d;
494 }
495
496 void SMESHDS_SubMesh::compactList()
497 {
498   if ( myUnusedIdElements > 0 )
499   {
500     std::vector<const SMDS_MeshElement*> newElems;
501     newElems.reserve( myElements.size() - myUnusedIdElements );
502     for (size_t i = 0; i < myElements.size(); i++)
503       if (myElements[i])
504       {
505         SMDS_MeshElement* elem = (SMDS_MeshElement*)myElements[i];
506         elem->setIdInShape(newElems.size());
507         newElems.push_back(elem);
508       }
509     myElements.swap(newElems);
510     myUnusedIdElements = 0;
511   }
512
513   if ( myUnusedIdNodes > 0 )
514   {
515     std::vector<const SMDS_MeshNode*> newNodes;
516     newNodes.reserve( myNodes.size() - myUnusedIdNodes );
517     for (size_t i = 0; i < myNodes.size(); i++)
518       if (myNodes[i])
519       {
520         SMDS_MeshNode* node = (SMDS_MeshNode*)myNodes[i];
521         node->setIdInShape(newNodes.size());
522         newNodes.push_back(node);
523       }
524     myNodes.swap(newNodes);
525     myUnusedIdNodes = 0;
526   }
527 }