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