Salome HOME
PR: debug SMDS memimp
[modules/smesh.git] / src / SMESHDS / SMESHDS_SubMesh.cxx
1 //  Copyright (C) 2007-2008  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 //  SMESH SMESHDS : management of mesh data and SMESH document
23 //  File   : SMESH_SubMesh.cxx
24 //  Author : Yves FRICAUD, OCC
25 //  Module : SMESH
26 //  $Header: 
27 //
28 #include "SMESHDS_SubMesh.hxx"
29
30 #include "utilities.h"
31 #include "SMDS_SetIterator.hxx"
32 #include <iostream>
33 #include <cassert>
34
35 using namespace std;
36
37 SMESHDS_SubMesh::SMESHDS_SubMesh()
38 {
39   myElements.clear();
40   myNodes.clear();
41   myUnusedIdNodes = 0;
42   myUnusedIdElements = 0;
43 }
44
45 //=======================================================================
46 //function : AddElement
47 //purpose  : 
48 //=======================================================================
49 void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * ME)
50 {
51   if ( !IsComplexSubmesh() )
52     {
53       int idInSubShape = ME->getIdInShape();
54       assert(idInSubShape == -1);
55       SMDS_MeshElement* elem = (SMDS_MeshElement*)(ME);
56       elem->setIdInShape(myElements.size());
57       myElements.push_back(ME);
58     }
59 }
60
61 //=======================================================================
62 //function : RemoveElement
63 //purpose  : 
64 //=======================================================================
65 bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * ME, bool isElemDeleted)
66 {
67 //      MESSAGE("--------------------------------------> RemoveElement " << isElemDeleted);
68 //  if ( !IsComplexSubmesh() && NbElements() ) {
69
70   if (!isElemDeleted) // alive element has valid ID and can be found
71       {
72         int idInSubShape = ME->getIdInShape();
73         //MESSAGE("SMESHDS_SubMesh::RemoveElement " << idInSubShape << " " << ME->GetID() << " " << myUnusedIdElements);
74         assert(idInSubShape >= 0);
75         assert(idInSubShape < myElements.size());
76         myElements[idInSubShape] = 0; // this vector entry is no more used
77         myUnusedIdElements++;
78         return true;
79       }
80
81     
82 // --- strange ?
83 //     TElemSet::iterator e = myElements.begin(), eEnd = myElements.end();
84 //     for ( ; e != eEnd; ++e )
85 //       if ( ME == *e ) {
86 //         myElements.erase( e );
87 //         return true;
88 //       }
89 //   }
90   
91   return false;
92 }
93
94 //=======================================================================
95 //function : AddNode
96 //purpose  : 
97 //=======================================================================
98 void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
99 {
100   if ( !IsComplexSubmesh() )
101     {
102       int idInSubShape = N->getIdInShape();
103       assert(idInSubShape == -1);
104       SMDS_MeshNode* node = (SMDS_MeshNode*)(N);
105       node->setIdInShape(myNodes.size());
106       myNodes.push_back(N);
107     }
108 }
109
110 //=======================================================================
111 //function : RemoveNode
112 //purpose  : 
113 //=======================================================================
114
115 bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N, bool isNodeDeleted)
116 {
117 //   if ( !IsComplexSubmesh() && NbNodes() ) {
118
119     if (!isNodeDeleted) // alive node has valid ID and can be found
120       {
121         int idInSubShape = N->getIdInShape();
122         //MESSAGE("SMESHDS_SubMesh::RemoveNode " << idInSubShape << " " << N->GetID());
123         assert(idInSubShape >= 0);
124         assert(idInSubShape < myNodes.size());
125         myNodes[idInSubShape] = 0; // this vector entry is no more used
126         myUnusedIdNodes++;
127         return true;
128       }
129
130 // --- strange ?
131 //     TElemSet::iterator e = myNodes.begin(), eEnd = myNodes.end();
132 //     for ( ; e != eEnd; ++e )
133 //       if ( N == *e ) {
134 //         myNodes.erase( e );
135 //         return true;
136 //       }
137 //   }
138
139   return false;
140 }
141
142 //=======================================================================
143 //function : NbElements
144 //purpose  : 
145 //=======================================================================
146 int SMESHDS_SubMesh::NbElements() const
147 {
148   if ( !IsComplexSubmesh() )
149     return myElements.size() - myUnusedIdElements;
150
151   int nbElems = 0;
152   set<const SMESHDS_SubMesh*>::const_iterator it = mySubMeshes.begin();
153   for ( ; it != mySubMeshes.end(); it++ )
154     nbElems += (*it)->NbElements();
155
156   return nbElems;
157 }
158
159 //=======================================================================
160 //function : NbNodes
161 //purpose  : 
162 //=======================================================================
163
164 int SMESHDS_SubMesh::NbNodes() const
165 {
166  if ( !IsComplexSubmesh() )
167    return myNodes.size() - myUnusedIdNodes;
168
169   int nbElems = 0;
170   set<const SMESHDS_SubMesh*>::const_iterator it = mySubMeshes.begin();
171   for ( ; it != mySubMeshes.end(); it++ )
172     nbElems += (*it)->NbNodes();
173
174   return nbElems;
175 }
176
177 /*!
178  * template class used for iteration on submesh elements. Interface of iterator remains
179  * unchanged after redesign of SMDS to avoid modification everywhere in SMESH.
180  * instances are stored in shared_ptr for automatic destruction.
181  * Container is copied for iteration, because original can be modified
182  * by addition of elements, for instance, and then reallocated (vector)
183  */
184 template <class ELEM, typename TSET> class MySetIterator : public SMDS_Iterator<ELEM>
185 {
186 protected:
187   typename TSET::const_iterator _it, _end;
188   TSET _table;
189 //  int _ind;
190 public:
191   MySetIterator(const TSET& table)
192 //  : _it(table.begin()), _end(table.end())
193   {
194 //        MESSAGE("table.size()="<< table.size());
195           _table = table;
196           _it = _table.begin();
197           _end = _table.end();
198 //        for (int i=0; i< _table.size(); i++)
199 //                if (_table[i]) { MESSAGE("_table["<< i << "]="<< _table[i]);}
200 //                else
201 //                { MESSAGE("_table["<< i << "]=NULL"); }
202 //        _ind = 0;
203   }
204
205   virtual bool more()
206   {
207     while((_it != _end) && (*_it == 0))
208     {
209       _it++;
210 //      _ind++;
211     }
212 //    MESSAGE("more _ind=" << _ind);
213     return (_it != _end);
214   }
215
216   virtual ELEM next()
217   {
218         ELEM e=*_it;
219 //      if (e) { MESSAGE("next _ind=" << _ind << " *_it=" << *_it);}
220 //      else { MESSAGE("next _ind=" << _ind << " *_it=NULL");}
221 //      _ind++;
222         _it++;
223         return e;
224   }
225 };
226
227 // =====================
228 // class MyIterator
229 // =====================
230
231 template<typename VALUE> class MyIterator : public SMDS_Iterator<VALUE>
232 {
233  public:
234   MyIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
235     : mySubIt( theSubMeshes.begin() ), mySubEnd( theSubMeshes.end() ), myMore(false)
236     {}
237   bool more()
238   {
239     while (( !myElemIt.get() || !myElemIt->more() ) && mySubIt != mySubEnd)
240     {
241       myElemIt = getElements(*mySubIt);
242       mySubIt++;
243     }
244     myMore = myElemIt.get() && myElemIt->more();
245     return myMore;
246   }
247   VALUE next()
248   {
249     VALUE elem = 0;
250     if ( myMore )
251       elem = myElemIt->next();
252     return elem;
253   }
254  protected:
255   virtual boost::shared_ptr< SMDS_Iterator<VALUE> >
256     getElements(const SMESHDS_SubMesh*) const = 0;
257
258  private:
259   bool                                        myMore;
260   set<const SMESHDS_SubMesh*>::const_iterator mySubIt, mySubEnd;
261   boost::shared_ptr< SMDS_Iterator<VALUE> >   myElemIt;
262 };
263
264 // =====================
265 // class MyElemIterator
266 // =====================
267
268 class MyElemIterator: public MyIterator<const SMDS_MeshElement*>
269 {
270  public:
271   MyElemIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
272     :MyIterator<const SMDS_MeshElement*>( theSubMeshes ) {}
273   SMDS_ElemIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
274   { return theSubMesh->GetElements(); }
275 };
276
277 // =====================
278 // class MyNodeIterator
279 // =====================
280
281 class MyNodeIterator: public MyIterator<const SMDS_MeshNode*>
282 {
283  public:
284   MyNodeIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
285     :MyIterator<const SMDS_MeshNode*>( theSubMeshes ) {}
286   SMDS_NodeIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
287   { return theSubMesh->GetNodes(); }
288 };
289   
290 //=======================================================================
291 //function : GetElements
292 //purpose  : 
293 //=======================================================================
294
295 SMDS_ElemIteratorPtr SMESHDS_SubMesh::GetElements() const
296 {
297   if ( IsComplexSubmesh() )
298     return SMDS_ElemIteratorPtr( new MyElemIterator( mySubMeshes ));
299   return SMDS_ElemIteratorPtr(new MySetIterator<const SMDS_MeshElement*, std::vector<const SMDS_MeshElement*> >(myElements));
300 }
301
302 //=======================================================================
303 //function : GetNodes
304 //purpose  : 
305 //=======================================================================
306
307 SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const
308 {
309   if ( IsComplexSubmesh() )
310     return SMDS_NodeIteratorPtr( new MyNodeIterator( mySubMeshes ));
311
312   return SMDS_NodeIteratorPtr(new MySetIterator<const SMDS_MeshNode*, std::vector<const SMDS_MeshNode*> >(myNodes));
313 }
314
315 //=======================================================================
316 //function : Contains
317 //purpose  : check if elem or node is in
318 //=======================================================================
319
320 bool SMESHDS_SubMesh::Contains(const SMDS_MeshElement * ME) const
321 {
322   // DO NOT TRY TO FIND A REMOVED ELEMENT !!
323   //if ( IsComplexSubmesh() || !ME )
324   if (!ME )
325     return false;
326
327   if ( IsComplexSubmesh() )
328   {
329     set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
330     for ( ; aSubIt != mySubMeshes.end(); aSubIt++ )
331       if ( (*aSubIt)->Contains( ME ))
332         return true;
333     return false;
334   }
335
336   if ( ME->GetType() == SMDSAbs_Node )
337     {
338       int idInShape = ME->getIdInShape();
339       if ((idInShape >= 0) && (idInShape < myNodes.size()))
340         if (myNodes[idInShape] == ME) return true;
341     }
342   else
343     {
344       int idInShape = ME->getIdInShape();
345       if ((idInShape >= 0) && (idInShape < myElements.size()))
346         if (myElements[idInShape] == ME) return true;
347     }
348     return false;
349 }
350
351 //=======================================================================
352 //function : AddSubMesh
353 //purpose  : 
354 //=======================================================================
355
356 void SMESHDS_SubMesh::AddSubMesh( const SMESHDS_SubMesh* theSubMesh )
357 {
358   ASSERT( theSubMesh );
359   mySubMeshes.insert( theSubMesh );
360 }
361
362 //=======================================================================
363 //function : RemoveSubMesh
364 //purpose  : 
365 //=======================================================================
366
367 bool SMESHDS_SubMesh::RemoveSubMesh( const SMESHDS_SubMesh* theSubMesh )
368 {
369   return mySubMeshes.erase( theSubMesh );
370 }
371
372 //=======================================================================
373 //function : ContainsSubMesh
374 //purpose  : 
375 //=======================================================================
376
377 bool SMESHDS_SubMesh::ContainsSubMesh( const SMESHDS_SubMesh* theSubMesh ) const
378 {
379   return mySubMeshes.find( theSubMesh ) != mySubMeshes.end();
380 }
381
382 //=======================================================================
383 //function : GetSubMeshIterator
384 //purpose  : 
385 //=======================================================================
386
387 SMESHDS_SubMeshIteratorPtr SMESHDS_SubMesh::GetSubMeshIterator() const
388 {
389   typedef set<const SMESHDS_SubMesh*>::const_iterator TIterator;
390   return SMESHDS_SubMeshIteratorPtr
391     ( new SMDS_SetIterator< const SMESHDS_SubMesh*, TIterator >( mySubMeshes.begin(),
392                                                                  mySubMeshes.end()));
393 }
394
395 //=======================================================================
396 //function : Clear
397 //purpose  : remove the contents
398 //=======================================================================
399
400 void SMESHDS_SubMesh::Clear()
401 {
402   myElements.clear();
403   myNodes.clear();
404   SMESHDS_SubMeshIteratorPtr sub = GetSubMeshIterator();
405   while ( sub->more() ) {
406     if ( SMESHDS_SubMesh* sm = (SMESHDS_SubMesh*) sub->next())
407       sm->Clear();
408   }
409 }
410
411 int SMESHDS_SubMesh::getSize()
412 {
413   int c = NbNodes();
414   int d = NbElements();
415   //cerr << "SMESHDS_SubMesh::NbNodes " << c << endl;
416   //cerr << "SMESHDS_SubMesh::NbElements " << d << endl;
417   return c+d;
418 }
419
420 void SMESHDS_SubMesh::compactList()
421 {
422         // todo : compact vector of nodes and elements
423 }