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