Salome HOME
32f89c9a62983ed7a61ef996cef37494967aec95
[modules/smesh.git] / src / SMESHDS / SMESHDS_SubMesh.cxx
1 // Copyright (C) 2007-2015  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, or (at your option) any later version.
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   myIndex = index;
50   myUnusedIdNodes = 0;
51   myUnusedIdElements = 0;
52 }
53
54 //================================================================================
55 /*!
56  * \brief Destructor
57  */
58 //================================================================================
59
60 SMESHDS_SubMesh::~SMESHDS_SubMesh()
61 {
62 }
63
64 //=======================================================================
65 //function : AddElement
66 //purpose  :
67 //=======================================================================
68
69 void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * ME)
70 {
71   if (!IsComplexSubmesh())
72   {
73     if ( ME->GetType() == SMDSAbs_Node )
74     {
75       AddNode( static_cast< const SMDS_MeshNode* >( ME ));
76       return;
77     }
78     int oldShapeId = ME->getshapeId();
79     if ( oldShapeId > 0 )
80     {
81       if (oldShapeId != myIndex)
82       {
83         throw SALOME_Exception
84           (LOCALIZED("add element in subshape already belonging to a subshape"));
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 >= (int)myElements.size())
93         {
94           throw SALOME_Exception(LOCALIZED("out of bounds"));
95         }
96         if (ME != myElements[idInSubShape])
97         {
98           throw SALOME_Exception(LOCALIZED("not the same element"));
99         }
100         return;
101       }
102     }
103
104     SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
105     elem->setShapeId(myIndex);
106     elem->setIdInShape(myElements.size());
107     myElements.push_back(ME);
108   }
109 }
110
111 //=======================================================================
112 //function : RemoveElement
113 //purpose  :
114 //=======================================================================
115
116 bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * ME, bool isElemDeleted)
117 {
118   if (!ME)
119   {
120     MESSAGE("-----------------> Remove Null Element " << isElemDeleted);
121     return false;
122   }
123   if (!IsComplexSubmesh())
124   {
125     if ( ME->getshapeId() != myIndex )
126       return false;
127     int idInSubShape = ME->getIdInShape();
128     SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
129     elem->setShapeId(0);
130     elem->setIdInShape(-1);
131     if ((idInSubShape >= 0) && (idInSubShape < (int) myElements.size()))
132     {
133       myElements[idInSubShape] = 0; // this vector entry is no more used
134       if ( ++myUnusedIdElements == (int) myElements.size() )
135       {
136         clearVector( myElements );
137         myUnusedIdElements = 0;
138       }
139       return true;
140     }
141     return false;
142   }
143   MESSAGE("Try to remove an element from a complex submesh ");
144   return false;
145 }
146
147 //=======================================================================
148 //function : AddNode
149 //purpose  : 
150 //=======================================================================
151
152 void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
153 {
154   if ( !IsComplexSubmesh() )
155   {
156     const int idInSubShape = N->getIdInShape();
157     const int shapeId      = N->getshapeId();
158     if ((shapeId > 0) && (idInSubShape >= 0))
159     {
160       if ( shapeId != myIndex )
161         throw SALOME_Exception
162           (LOCALIZED("a node being in sub-mesh is added to another sub-mesh"));
163       if ( idInSubShape >= (int)myNodes.size() || myNodes[ idInSubShape ] != N )
164         throw SALOME_Exception
165           (LOCALIZED("a node with wrong idInSubShape is re-added to the same sub-mesh"));
166       return; // already in
167     }
168     SMDS_MeshNode* node = (SMDS_MeshNode*)(N);
169     node->setShapeId(myIndex);
170     node->setIdInShape(myNodes.size());
171     myNodes.push_back(N);
172   }
173 }
174
175 //=======================================================================
176 //function : RemoveNode
177 //purpose  :
178 //=======================================================================
179
180 bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N, bool isNodeDeleted)
181 {
182   if (!IsComplexSubmesh())
183   {
184     if ( N->getshapeId() != myIndex )
185       return false;
186     int idInSubShape = N->getIdInShape();
187     SMDS_MeshNode* node = (SMDS_MeshNode*) (N);
188     node->setShapeId(0);
189     node->setIdInShape(-1);
190     if ((idInSubShape >= 0) && (idInSubShape < (int) myNodes.size()))
191     {
192       myNodes[idInSubShape] = 0; // this vector entry is no more used
193       if ( ++myUnusedIdNodes == (int) myNodes.size() )
194       {
195         clearVector( myNodes );
196         myUnusedIdNodes = 0;
197       }
198       return true;
199     }
200     return false;
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
211 int SMESHDS_SubMesh::NbElements() const
212 {
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   if ( !IsComplexSubmesh() )
232     return myNodes.size() - myUnusedIdNodes;
233
234   int nbElems = 0;
235   set<const SMESHDS_SubMesh*>::const_iterator it = mySubMeshes.begin();
236   for ( ; it != mySubMeshes.end(); it++ )
237     nbElems += (*it)->NbNodes();
238
239   return nbElems;
240 }
241
242 /*!
243  * template class used for iteration on submesh elements. Interface of iterator remains
244  * unchanged after redesign of SMDS to avoid modification everywhere in SMESH.
245  * instances are stored in shared_ptr for automatic destruction.
246  * Container is copied for iteration, because original can be modified
247  * by addition of elements, for instance, and then reallocated (vector)
248  */
249 template <class ELEM, typename TSET> class MySetIterator : public SMDS_Iterator<ELEM>
250 {
251 protected:
252   typename TSET::const_iterator _it, _end;
253   TSET _table;
254 public:
255   MySetIterator(const TSET& table)
256   {
257     _table = table;
258     _it = _table.begin();
259     _end = _table.end();
260     while ((_it != _end) && (*_it == 0))
261       _it++;
262   }
263
264   virtual bool more()
265   {
266     while ((_it != _end) && (*_it == 0))
267       _it++;
268     return (_it != _end);
269   }
270
271   virtual ELEM next()
272   {
273     ELEM e = *_it;
274     _it++;
275     return e;
276   }
277 };
278
279 // =====================
280 // class MyIterator
281 // =====================
282
283 template<typename VALUE> class MyIterator : public SMDS_Iterator<VALUE>
284 {
285  public:
286   MyIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
287     : myMore(false), mySubIt( theSubMeshes.begin() ), mySubEnd( theSubMeshes.end() )
288     {}
289   bool more()
290   {
291     while (( !myElemIt.get() || !myElemIt->more() ) && mySubIt != mySubEnd)
292     {
293       myElemIt = getElements(*mySubIt);
294       mySubIt++;
295     }
296     myMore = myElemIt.get() && myElemIt->more();
297     return myMore;
298   }
299   VALUE next()
300   {
301     VALUE elem = 0;
302     if ( myMore )
303       elem = myElemIt->next();
304     return elem;
305   }
306  protected:
307   virtual boost::shared_ptr< SMDS_Iterator<VALUE> >
308     getElements(const SMESHDS_SubMesh*) const = 0;
309
310  private:
311   bool                                        myMore;
312   set<const SMESHDS_SubMesh*>::const_iterator mySubIt, mySubEnd;
313   boost::shared_ptr< SMDS_Iterator<VALUE> >   myElemIt;
314 };
315
316 // =====================
317 // class MyElemIterator
318 // =====================
319
320 class MyElemIterator: public MyIterator<const SMDS_MeshElement*>
321 {
322  public:
323   MyElemIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
324     :MyIterator<const SMDS_MeshElement*>( theSubMeshes ) {}
325   SMDS_ElemIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
326   { return theSubMesh->GetElements(); }
327 };
328
329 // =====================
330 // class MyNodeIterator
331 // =====================
332
333 class MyNodeIterator: public MyIterator<const SMDS_MeshNode*>
334 {
335  public:
336   MyNodeIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
337     :MyIterator<const SMDS_MeshNode*>( theSubMeshes ) {}
338   SMDS_NodeIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
339   { return theSubMesh->GetNodes(); }
340 };
341   
342 //=======================================================================
343 //function : GetElements
344 //purpose  : 
345 //=======================================================================
346
347 SMDS_ElemIteratorPtr SMESHDS_SubMesh::GetElements() const
348 {
349   if ( IsComplexSubmesh() )
350     return SMDS_ElemIteratorPtr( new MyElemIterator( mySubMeshes ));
351   return SMDS_ElemIteratorPtr(new MySetIterator<const SMDS_MeshElement*, std::vector<const SMDS_MeshElement*> >(myElements));
352 }
353
354 //=======================================================================
355 //function : GetNodes
356 //purpose  : 
357 //=======================================================================
358
359 SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const
360 {
361   if ( IsComplexSubmesh() )
362     return SMDS_NodeIteratorPtr( new MyNodeIterator( mySubMeshes ));
363
364   return SMDS_NodeIteratorPtr(new MySetIterator<const SMDS_MeshNode*, std::vector<const SMDS_MeshNode*> >(myNodes));
365 }
366
367 //=======================================================================
368 //function : Contains
369 //purpose  : check if elem or node is in
370 //=======================================================================
371
372 bool SMESHDS_SubMesh::Contains(const SMDS_MeshElement * ME) const
373 {
374   // DO NOT TRY TO FIND A REMOVED ELEMENT !!
375   //if ( IsComplexSubmesh() || !ME )
376   if (!ME)
377     return false;
378
379   if ( IsComplexSubmesh() )
380   {
381     set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
382     for (; aSubIt != mySubMeshes.end(); aSubIt++)
383       if ((*aSubIt)->Contains(ME))
384         return true;
385     return false;
386   }
387
388   if (ME->GetType() == SMDSAbs_Node)
389   {
390     int idInShape = ME->getIdInShape();
391     if ((idInShape >= 0) && (idInShape < (int) myNodes.size()))
392       if (myNodes[idInShape] == ME)
393         return true;
394   }
395   else
396   {
397     int idInShape = ME->getIdInShape();
398     if ((idInShape >= 0) && (idInShape < (int) myElements.size()))
399       if (myElements[idInShape] == ME)
400         return true;
401   }
402   return false;
403 }
404
405 //=======================================================================
406 //function : IsQuadratic
407 //purpose  : Return true if my 1st element is quadratic
408 //=======================================================================
409
410 bool SMESHDS_SubMesh::IsQuadratic() const
411 {
412   if ( IsComplexSubmesh() )
413   {
414     set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
415     for (; aSubIt != mySubMeshes.end(); aSubIt++)
416       if ((*aSubIt)->IsQuadratic())
417         return true;
418     return false;
419   }
420
421   for ( size_t i = 0; i < myElements.size(); ++i )
422     if ( myElements[i] )
423       return myElements[i]->IsQuadratic();
424
425   return false;
426 }
427
428 //=======================================================================
429 //function : AddSubMesh
430 //purpose  : 
431 //=======================================================================
432
433 void SMESHDS_SubMesh::AddSubMesh( const SMESHDS_SubMesh* theSubMesh )
434 {
435   ASSERT( theSubMesh );
436   mySubMeshes.insert( theSubMesh );
437 }
438
439 //=======================================================================
440 //function : RemoveSubMesh
441 //purpose  : 
442 //=======================================================================
443
444 bool SMESHDS_SubMesh::RemoveSubMesh( const SMESHDS_SubMesh* theSubMesh )
445 {
446   return mySubMeshes.erase( theSubMesh );
447 }
448
449 //=======================================================================
450 //function : RemoveAllSubmeshes
451 //purpose  : 
452 //=======================================================================
453
454 void SMESHDS_SubMesh::RemoveAllSubmeshes()
455 {
456   mySubMeshes.clear();
457 }
458
459 //=======================================================================
460 //function : ContainsSubMesh
461 //purpose  : 
462 //=======================================================================
463
464 bool SMESHDS_SubMesh::ContainsSubMesh( const SMESHDS_SubMesh* theSubMesh ) const
465 {
466   return mySubMeshes.find( theSubMesh ) != mySubMeshes.end();
467 }
468
469 //=======================================================================
470 //function : GetSubMeshIterator
471 //purpose  : 
472 //=======================================================================
473
474 SMESHDS_SubMeshIteratorPtr SMESHDS_SubMesh::GetSubMeshIterator() const
475 {
476   typedef set<const SMESHDS_SubMesh*>::const_iterator TIterator;
477   return SMESHDS_SubMeshIteratorPtr
478     ( new SMDS_SetIterator< const SMESHDS_SubMesh*, TIterator >( mySubMeshes.begin(),
479                                                                  mySubMeshes.end()));
480 }
481
482 //=======================================================================
483 //function : Clear
484 //purpose  : remove the contents
485 //=======================================================================
486
487 void SMESHDS_SubMesh::Clear()
488 {
489   clearVector( myElements );
490   clearVector( myNodes );
491   myUnusedIdNodes = 0;
492   myUnusedIdElements = 0;
493   if ( NbSubMeshes() > 0 )
494   {
495     SMESHDS_SubMeshIteratorPtr sub = GetSubMeshIterator();
496     while ( sub->more() ) {
497       if ( SMESHDS_SubMesh* sm = (SMESHDS_SubMesh*) sub->next())
498         sm->Clear();
499     }
500   }
501 }
502
503 int SMESHDS_SubMesh::getSize()
504 {
505   int c = NbNodes();
506   int d = NbElements();
507   return c+d;
508 }
509
510 void SMESHDS_SubMesh::compactList()
511 {
512   if ( myUnusedIdElements > 0 )
513   {
514     std::vector<const SMDS_MeshElement*> newElems;
515     newElems.reserve( myElements.size() - myUnusedIdElements );
516     for (size_t i = 0; i < myElements.size(); i++)
517       if (myElements[i])
518       {
519         SMDS_MeshElement* elem = (SMDS_MeshElement*)myElements[i];
520         elem->setIdInShape(newElems.size());
521         newElems.push_back(elem);
522       }
523     myElements.swap(newElems);
524     myUnusedIdElements = 0;
525   }
526
527   if ( myUnusedIdNodes > 0 )
528   {
529     std::vector<const SMDS_MeshNode*> newNodes;
530     newNodes.reserve( myNodes.size() - myUnusedIdNodes );
531     for (size_t i = 0; i < myNodes.size(); i++)
532       if (myNodes[i])
533       {
534         SMDS_MeshNode* node = (SMDS_MeshNode*)myNodes[i];
535         node->setIdInShape(newNodes.size());
536         newNodes.push_back(node);
537       }
538     myNodes.swap(newNodes);
539     myUnusedIdNodes = 0;
540   }
541 }
542
543 //=======================================================================
544 //function : GetElement
545 //purpose  : Return an element by its IdInShape
546 //=======================================================================
547
548 const SMDS_MeshElement* SMESHDS_SubMesh::GetElement( size_t idInShape ) const
549 {
550   return ( !IsComplexSubmesh() && idInShape < myElements.size() ) ? myElements[idInShape] : 0;
551 }
552
553 //=======================================================================
554 //function : GetElement
555 //purpose  : Return a node by its IdInShape
556 //=======================================================================
557
558 const SMDS_MeshNode* SMESHDS_SubMesh::GetNode( size_t idInShape ) const
559 {
560   return ( !IsComplexSubmesh() && idInShape < myNodes.size() ) ? myNodes[idInShape] : 0;
561 }