Salome HOME
Merge from V6_main_20120808 08Aug12
[modules/smesh.git] / src / SMESHDS / SMESHDS_SubMesh.cxx
1 // Copyright (C) 2007-2012  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.
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 void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * ME)
71 {
72   if (!IsComplexSubmesh())
73     {
74       if ( ME->GetType() == SMDSAbs_Node )
75       {
76         AddNode( static_cast< const SMDS_MeshNode* >( ME ));
77         return;
78       }
79       //MESSAGE("in " << myIndex << " AddElement "<< ME->GetID());
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 bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * ME, bool isElemDeleted)
125 {
126   if (!ME)
127     {
128       MESSAGE("-----------------> Remove Null Element " << isElemDeleted);
129       return false;
130     }
131   //MESSAGE("-----------------> RemoveElement "<< ME->GetID() << " " << isElemDeleted);
132   if (!IsComplexSubmesh())
133     {
134       if ( ME->getshapeId() != myIndex )
135         return false;
136       int idInSubShape = ME->getIdInShape();
137       //MESSAGE("in "<< myIndex << " RemoveElement " << ME->GetID() << " " << idInSubShape << " " << myUnusedIdElements);
138       SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
139       elem->setShapeId(0);
140       elem->setIdInShape(-1);
141       if ((idInSubShape >= 0) && (idInSubShape < myElements.size()))
142         {
143           myElements[idInSubShape] = 0; // this vector entry is no more used
144           myUnusedIdElements++;
145           return true;
146         }
147       return false;
148       //  }
149     }
150   MESSAGE("Try to remove an element from a complex submesh ");
151   return false;
152 }
153
154 //=======================================================================
155 //function : AddNode
156 //purpose  : 
157 //=======================================================================
158 void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
159 {
160   if ( !IsComplexSubmesh() )
161     {
162       int idInSubShape = N->getIdInShape();
163       int shapeId = N->getshapeId();
164       if ((shapeId > 0) && (idInSubShape >= 0))
165         {
166 //           MESSAGE("========== AddNode already belonging to other subShape " << N->GetID());
167           // OK for vertex nodes
168           throw SALOME_Exception(LOCALIZED("add node in subshape already belonging to a subshape"));
169         }
170       SMDS_MeshNode* node = (SMDS_MeshNode*)(N);
171       node->setShapeId(myIndex);
172       node->setIdInShape(myNodes.size());
173       myNodes.push_back(N);
174       //MESSAGE("in "<< myIndex << " AddNode " << node->GetID());
175     }
176   //MESSAGE("try to add node in a complex submesh " << N->GetID());
177 }
178
179 //=======================================================================
180 //function : RemoveNode
181 //purpose  : 
182 //=======================================================================
183
184 bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N, bool isNodeDeleted)
185 {
186   if (!IsComplexSubmesh())
187     {
188       // if (!isNodeDeleted) // alive node has valid ID and can be found
189       // {
190       if ( N->getshapeId() != myIndex )
191         return false;
192       int idInSubShape = N->getIdInShape();
193       //int shapeId = N->getshapeId();
194       //MESSAGE("in "<< myIndex << " RemoveNode " << shapeId << " " << idInSubShape << " " << N->GetID());
195       SMDS_MeshNode* node = (SMDS_MeshNode*) (N);
196       node->setShapeId(0);
197       node->setIdInShape(-1);
198       if ((idInSubShape >= 0) && (idInSubShape < myNodes.size()))
199         {
200           myNodes[idInSubShape] = 0; // this vector entry is no more used
201           myUnusedIdNodes++;
202           return true;
203         }
204       return false;
205       // }
206     }
207   MESSAGE("Try to remove a node from a complex submesh");
208   return false;
209 }
210
211 //=======================================================================
212 //function : NbElements
213 //purpose  : 
214 //=======================================================================
215 int SMESHDS_SubMesh::NbElements() const
216 {
217   //MESSAGE(this << " NbElements " << IsComplexSubmesh() << " " << myElements.size() - myUnusedIdElements);
218   if ( !IsComplexSubmesh() )
219     return myElements.size() - myUnusedIdElements;
220
221   int nbElems = 0;
222   set<const SMESHDS_SubMesh*>::const_iterator it = mySubMeshes.begin();
223   for ( ; it != mySubMeshes.end(); it++ )
224     nbElems += (*it)->NbElements();
225
226   return nbElems;
227 }
228
229 //=======================================================================
230 //function : NbNodes
231 //purpose  : 
232 //=======================================================================
233
234 int SMESHDS_SubMesh::NbNodes() const
235 {
236   //MESSAGE(this << " NbNodes " << IsComplexSubmesh() << " " << myNodes.size() - myUnusedIdNodes);
237   if ( !IsComplexSubmesh() )
238     return myNodes.size() - myUnusedIdNodes;
239
240   int nbElems = 0;
241   set<const SMESHDS_SubMesh*>::const_iterator it = mySubMeshes.begin();
242   for ( ; it != mySubMeshes.end(); it++ )
243     nbElems += (*it)->NbNodes();
244
245   return nbElems;
246 }
247
248 /*!
249  * template class used for iteration on submesh elements. Interface of iterator remains
250  * unchanged after redesign of SMDS to avoid modification everywhere in SMESH.
251  * instances are stored in shared_ptr for automatic destruction.
252  * Container is copied for iteration, because original can be modified
253  * by addition of elements, for instance, and then reallocated (vector)
254  */
255 template <class ELEM, typename TSET> class MySetIterator : public SMDS_Iterator<ELEM>
256 {
257 protected:
258   typename TSET::const_iterator _it, _end;
259   TSET _table;
260 public:
261   MySetIterator(const TSET& table)
262   {
263     _table = table;
264     _it = _table.begin();
265     _end = _table.end();
266     while ((_it != _end) && (*_it == 0))
267       _it++;
268   }
269
270   virtual bool more()
271   {
272     while ((_it != _end) && (*_it == 0))
273       _it++;
274     return (_it != _end);
275   }
276
277   virtual ELEM next()
278   {
279     ELEM e = *_it;
280     _it++;
281     return e;
282   }
283 };
284
285 // =====================
286 // class MyIterator
287 // =====================
288
289 template<typename VALUE> class MyIterator : public SMDS_Iterator<VALUE>
290 {
291  public:
292   MyIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
293     : mySubIt( theSubMeshes.begin() ), mySubEnd( theSubMeshes.end() ), myMore(false)
294     {}
295   bool more()
296   {
297     while (( !myElemIt.get() || !myElemIt->more() ) && mySubIt != mySubEnd)
298     {
299       myElemIt = getElements(*mySubIt);
300       mySubIt++;
301     }
302     myMore = myElemIt.get() && myElemIt->more();
303     return myMore;
304   }
305   VALUE next()
306   {
307     VALUE elem = 0;
308     if ( myMore )
309       elem = myElemIt->next();
310     return elem;
311   }
312  protected:
313   virtual boost::shared_ptr< SMDS_Iterator<VALUE> >
314     getElements(const SMESHDS_SubMesh*) const = 0;
315
316  private:
317   bool                                        myMore;
318   set<const SMESHDS_SubMesh*>::const_iterator mySubIt, mySubEnd;
319   boost::shared_ptr< SMDS_Iterator<VALUE> >   myElemIt;
320 };
321
322 // =====================
323 // class MyElemIterator
324 // =====================
325
326 class MyElemIterator: public MyIterator<const SMDS_MeshElement*>
327 {
328  public:
329   MyElemIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
330     :MyIterator<const SMDS_MeshElement*>( theSubMeshes ) {}
331   SMDS_ElemIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
332   { return theSubMesh->GetElements(); }
333 };
334
335 // =====================
336 // class MyNodeIterator
337 // =====================
338
339 class MyNodeIterator: public MyIterator<const SMDS_MeshNode*>
340 {
341  public:
342   MyNodeIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
343     :MyIterator<const SMDS_MeshNode*>( theSubMeshes ) {}
344   SMDS_NodeIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
345   { return theSubMesh->GetNodes(); }
346 };
347   
348 //=======================================================================
349 //function : GetElements
350 //purpose  : 
351 //=======================================================================
352
353 SMDS_ElemIteratorPtr SMESHDS_SubMesh::GetElements() const
354 {
355   if ( IsComplexSubmesh() )
356     return SMDS_ElemIteratorPtr( new MyElemIterator( mySubMeshes ));
357   return SMDS_ElemIteratorPtr(new MySetIterator<const SMDS_MeshElement*, std::vector<const SMDS_MeshElement*> >(myElements));
358 }
359
360 //=======================================================================
361 //function : GetNodes
362 //purpose  : 
363 //=======================================================================
364
365 SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const
366 {
367   if ( IsComplexSubmesh() )
368     return SMDS_NodeIteratorPtr( new MyNodeIterator( mySubMeshes ));
369
370   return SMDS_NodeIteratorPtr(new MySetIterator<const SMDS_MeshNode*, std::vector<const SMDS_MeshNode*> >(myNodes));
371 }
372
373 //=======================================================================
374 //function : Contains
375 //purpose  : check if elem or node is in
376 //=======================================================================
377
378 bool SMESHDS_SubMesh::Contains(const SMDS_MeshElement * ME) const
379 {
380   // DO NOT TRY TO FIND A REMOVED ELEMENT !!
381   //if ( IsComplexSubmesh() || !ME )
382   if (!ME)
383     return false;
384
385   if (IsComplexSubmesh())
386     {
387       set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
388       for (; aSubIt != mySubMeshes.end(); aSubIt++)
389         if ((*aSubIt)->Contains(ME))
390           return true;
391       return false;
392     }
393
394   if (ME->GetType() == SMDSAbs_Node)
395     {
396       int idInShape = ME->getIdInShape();
397       if ((idInShape >= 0) && (idInShape < myNodes.size()))
398         if (myNodes[idInShape] == ME)
399           return true;
400     }
401   else
402     {
403       int idInShape = ME->getIdInShape();
404       if ((idInShape >= 0) && (idInShape < myElements.size()))
405         if (myElements[idInShape] == ME)
406           return true;
407     }
408   return false;
409 }
410
411 //=======================================================================
412 //function : AddSubMesh
413 //purpose  : 
414 //=======================================================================
415
416 void SMESHDS_SubMesh::AddSubMesh( const SMESHDS_SubMesh* theSubMesh )
417 {
418   ASSERT( theSubMesh );
419   mySubMeshes.insert( theSubMesh );
420 }
421
422 //=======================================================================
423 //function : RemoveSubMesh
424 //purpose  : 
425 //=======================================================================
426
427 bool SMESHDS_SubMesh::RemoveSubMesh( const SMESHDS_SubMesh* theSubMesh )
428 {
429   return mySubMeshes.erase( theSubMesh );
430 }
431
432 //=======================================================================
433 //function : RemoveAllSubmeshes
434 //purpose  : 
435 //=======================================================================
436
437 void SMESHDS_SubMesh::RemoveAllSubmeshes()
438 {
439   mySubMeshes.clear();
440 }
441
442 //=======================================================================
443 //function : ContainsSubMesh
444 //purpose  : 
445 //=======================================================================
446
447 bool SMESHDS_SubMesh::ContainsSubMesh( const SMESHDS_SubMesh* theSubMesh ) const
448 {
449   return mySubMeshes.find( theSubMesh ) != mySubMeshes.end();
450 }
451
452 //=======================================================================
453 //function : GetSubMeshIterator
454 //purpose  : 
455 //=======================================================================
456
457 SMESHDS_SubMeshIteratorPtr SMESHDS_SubMesh::GetSubMeshIterator() const
458 {
459   typedef set<const SMESHDS_SubMesh*>::const_iterator TIterator;
460   return SMESHDS_SubMeshIteratorPtr
461     ( new SMDS_SetIterator< const SMESHDS_SubMesh*, TIterator >( mySubMeshes.begin(),
462                                                                  mySubMeshes.end()));
463 }
464
465 //=======================================================================
466 //function : Clear
467 //purpose  : remove the contents
468 //=======================================================================
469
470 void SMESHDS_SubMesh::Clear()
471 {
472   myElements.clear();
473   myNodes.clear();
474   myUnusedIdNodes = 0;
475   myUnusedIdElements = 0;
476   SMESHDS_SubMeshIteratorPtr sub = GetSubMeshIterator();
477   while ( sub->more() ) {
478     if ( SMESHDS_SubMesh* sm = (SMESHDS_SubMesh*) sub->next())
479       sm->Clear();
480   }
481 }
482
483 int SMESHDS_SubMesh::getSize()
484 {
485   int c = NbNodes();
486   int d = NbElements();
487   //cerr << "SMESHDS_SubMesh::NbNodes " << c << endl;
488   //cerr << "SMESHDS_SubMesh::NbElements " << d << endl;
489   return c+d;
490 }
491
492 void SMESHDS_SubMesh::compactList()
493 {
494   //MESSAGE("compactList old: nodes " << myNodes.size() << " elements " << myElements.size());
495   //stringstream a;
496   //stringstream b;
497   //stringstream c;
498   //stringstream d;
499
500   std::vector<const SMDS_MeshElement*> newElems;
501   newElems.clear();
502   for (int 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         //a << elem->GetID() << " ";
509         //b << elem->GetID() << " ";
510       }
511     //else
512     //  a << "_ ";
513   myElements.swap(newElems);
514   myUnusedIdElements = 0;
515   //MESSAGE("in " << myIndex << " oldElems " << a.str());
516   //MESSAGE("in " << myIndex << " newElems " << b.str());
517
518   std::vector<const SMDS_MeshNode*> newNodes;
519   newNodes.clear();
520   for (int i = 0; i < myNodes.size(); i++)
521     if (myNodes[i])
522       {
523         SMDS_MeshNode* node = (SMDS_MeshNode*)myNodes[i];
524         node->setIdInShape(newNodes.size());
525         newNodes.push_back(node);
526         //c << node->GetID() << " ";
527         //d << node->GetID() << " ";
528       }
529     //else
530     //  c << "_ ";
531   myNodes.swap(newNodes);
532   myUnusedIdNodes = 0;
533   //MESSAGE("in " << myIndex << " oldNodes " << c.str());
534   //MESSAGE("in " << myIndex << " newNodes " << d.str());
535   //MESSAGE("compactList new: nodes " << myNodes.size() << " elements " << myElements.size());
536 }