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