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