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