Salome HOME
Copyright update 2021
[modules/smesh.git] / src / SMESHDS / SMESHDS_SubMesh.cxx
1 // Copyright (C) 2007-2021  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
31 #include "SMDS_ElementFactory.hxx"
32 #include "SMDS_IteratorOnIterators.hxx"
33 #include "SMDS_SetIterator.hxx"
34 #include "SMESHDS_Mesh.hxx"
35
36 #include <utilities.h>
37
38 namespace
39 {
40   typedef const SMDS_MeshElement* PElem;
41   typedef const SMDS_MeshNode*    PNode;
42
43   typedef SMDS_SetIterator< PElem, PElem const *,
44                             SMDS::SimpleAccessor< PElem, PElem const * >,
45                             SMDS::NonNullFilter< PElem > >                 EArrayIterator;
46
47   typedef SMDS_SetIterator< PNode, PNode const *,
48                             SMDS::SimpleAccessor< PNode, PNode const * >,
49                             SMDS::NonNullFilter< PNode > >                 NArrayIterator;
50
51   int ind1st( SMDSAbs_ElementType t )
52   {
53     return t == SMDSAbs_Node;
54   }
55
56   //=======================================================================
57   //class : _MyElemIteratorFromNodeIterator
58   //=======================================================================
59   class _MyElemIteratorFromNodeIterator : public SMDS_ElemIterator
60   {
61     SMDS_NodeIteratorPtr myItr;
62   public:
63     _MyElemIteratorFromNodeIterator(SMDS_NodeIteratorPtr nodeItr): myItr( nodeItr ) {}
64     bool more()                    { return myItr->more(); }
65     const SMDS_MeshElement* next() { return myItr->next(); }
66   };
67 }
68
69 //================================================================================
70 /*!
71  * \brief Constructor
72  */
73 //================================================================================
74
75 SMESHDS_SubMesh::SMESHDS_SubMesh(const SMESHDS_Mesh *parent, int index)
76   : SMDS_ElementHolder( parent )
77 {
78   myParent = parent;
79   myIndex = index;
80   myNbElements = 0;
81   myNbNodes = 0;
82   my1stElemNode[0] = my1stElemNode[1] = 0;
83 }
84
85 //================================================================================
86 /*!
87  * \brief Destructor
88  */
89 //================================================================================
90
91 SMESHDS_SubMesh::~SMESHDS_SubMesh()
92 {
93 }
94
95 //=======================================================================
96 //function : AddElement
97 //purpose  :
98 //=======================================================================
99
100 void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * elem)
101 {
102   if (!IsComplexSubmesh())
103   {
104     if ( elem->GetType() == SMDSAbs_Node )
105     {
106       AddNode( static_cast< const SMDS_MeshNode* >( elem ));
107       return;
108     }
109     int oldShapeId = elem->GetShapeID();
110     if ( oldShapeId > 0 )
111     {
112       if (oldShapeId != myIndex)
113       {
114         throw SALOME_Exception
115           (LOCALIZED("add element in subshape already belonging to a subshape"));
116       }
117     }
118     else
119     {
120       ++myNbElements;
121     }
122
123     elem->setShapeID( myIndex );
124
125     // remember element with smallest ID to optimize iteration on them
126     add( elem );
127   }
128 }
129
130 //=======================================================================
131 //function : RemoveElement
132 //purpose  :
133 //=======================================================================
134
135 bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * elem )
136 {
137   if ( myNbElements == 0 || !elem || elem->IsNull() || elem->getshapeId() != myIndex )
138   {
139     return false;
140   }
141   if ( !IsComplexSubmesh() )
142   {
143     elem->setShapeID( 0 );
144     myNbElements--;
145
146     const SMDS_MeshElement* & elem1st = my1stElemNode[ ind1st( elem->GetType() )];
147     if ( elem1st == elem )
148     {
149       if ( myNbElements > 0 )
150       {
151         SMDS_ElemIteratorPtr it = myParent->shapeElementsIterator( myIndex, 1, elem1st );
152         if ( it->more() )
153           elem1st = it->next();
154         else
155           throw SALOME_Exception(LOCALIZED("invalid myNbElements"));
156       }
157       else
158       {
159         elem1st = 0;
160       }
161     }
162     return true;
163   }
164   return false;
165 }
166
167 //=======================================================================
168 //function : AddNode
169 //purpose  :
170 //=======================================================================
171
172 void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
173 {
174   if ( !IsComplexSubmesh() )
175   {
176     const int shapeId = N->getshapeId();
177     if ( shapeId > 0 )
178     {
179       if ( shapeId != myIndex )
180         throw SALOME_Exception
181           (LOCALIZED("a node being in sub-mesh is added to another sub-mesh"));
182       return; // already in
183     }
184     else
185     {
186       ++myNbNodes;
187     }
188     N->setShapeID( myIndex );
189
190     // remember node with smallest ID to optimize iteration on them
191     add( N );
192   }
193 }
194
195 //=======================================================================
196 //function : RemoveNode
197 //purpose  :
198 //=======================================================================
199
200 bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N)
201 {
202   if ( myNbNodes == 0 || !N || N->getshapeId() != myIndex )
203   {
204     return false;
205   }
206   if ( !IsComplexSubmesh() )
207   {
208     N->setShapeID( 0 );
209     myNbNodes--;
210
211     const SMDS_MeshElement* & node1st = my1stElemNode[ ind1st( SMDSAbs_Node )];
212     if ( node1st == N )
213     {
214       if ( myNbNodes > 0 )
215       {
216         SMDS_NodeIteratorPtr it =
217           myParent->shapeNodesIterator( myIndex, 1, static_cast< PNode >( node1st ));
218         if ( it->more() )
219           node1st = it->next();
220         else
221           throw SALOME_Exception(LOCALIZED("invalid myNbNodes"));
222       }
223       else
224       {
225         node1st = 0;
226       }
227     }
228     return true;
229   }
230   return false;
231 }
232
233 //=======================================================================
234 //function : NbElements
235 //purpose  :
236 //=======================================================================
237
238 int SMESHDS_SubMesh::NbElements() const
239 {
240   if ( !IsComplexSubmesh() )
241     return myNbElements;
242
243   int nbElems = 0;
244   TSubMeshSet::const_iterator it = mySubMeshes.begin();
245   for ( ; it != mySubMeshes.end(); it++ )
246     nbElems += (*it)->NbElements();
247
248   return nbElems;
249 }
250
251 //=======================================================================
252 //function : NbNodes
253 //purpose  :
254 //=======================================================================
255
256 int SMESHDS_SubMesh::NbNodes() const
257 {
258   if ( !IsComplexSubmesh() )
259     return myNbNodes;
260
261   int nbElems = 0;
262   TSubMeshSet::const_iterator it = mySubMeshes.begin();
263   for ( ; it != mySubMeshes.end(); it++ )
264     nbElems += (*it)->NbNodes();
265
266   return nbElems;
267 }
268
269 // =====================
270 // class MyIterator
271 // =====================
272
273 template<typename VALUE> class MyIterator : public SMDS_Iterator<VALUE>
274 {
275 public:
276   MyIterator (const TSubMeshSet& theSubMeshes)
277     : myMore(false), mySubIt( theSubMeshes.begin() ), mySubEnd( theSubMeshes.end() )
278   {}
279   bool more()
280   {
281     while (( !myElemIt.get() || !myElemIt->more() ) && mySubIt != mySubEnd)
282     {
283       myElemIt = getElements(*mySubIt);
284       mySubIt++;
285     }
286     myMore = myElemIt.get() && myElemIt->more();
287     return myMore;
288   }
289   VALUE next()
290   {
291     VALUE elem = 0;
292     if ( myMore )
293       elem = myElemIt->next();
294     return elem;
295   }
296 protected:
297   virtual boost::shared_ptr< SMDS_Iterator<VALUE> >
298   getElements(const SMESHDS_SubMesh*) const = 0;
299
300 private:
301   bool                                      myMore;
302   TSubMeshSet::const_iterator               mySubIt, mySubEnd;
303   boost::shared_ptr< SMDS_Iterator<VALUE> > myElemIt;
304 };
305
306 // =====================
307 // class MyElemIterator
308 // =====================
309
310 class MyElemIterator: public MyIterator<const SMDS_MeshElement*>
311 {
312 public:
313   MyElemIterator (const TSubMeshSet& theSubMeshes)
314     :MyIterator<const SMDS_MeshElement*>( theSubMeshes ) {}
315   SMDS_ElemIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
316   { return theSubMesh->GetElements(); }
317 };
318
319 // =====================
320 // class MyNodeIterator
321 // =====================
322
323 class MyNodeIterator: public MyIterator<const SMDS_MeshNode*>
324 {
325 public:
326   MyNodeIterator (const TSubMeshSet& theSubMeshes)
327     :MyIterator<const SMDS_MeshNode*>( theSubMeshes ) {}
328   SMDS_NodeIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
329   { return theSubMesh->GetNodes(); }
330 };
331
332 //=======================================================================
333 //function : GetElements
334 //purpose  :
335 //=======================================================================
336
337 SMDS_ElemIteratorPtr SMESHDS_SubMesh::GetElements() const
338 {
339   if ( IsComplexSubmesh() )
340     return SMDS_ElemIteratorPtr( new MyElemIterator( mySubMeshes ));
341
342   const SMDS_MeshElement* const * elem1st = & my1stElemNode[ ind1st( SMDSAbs_All )];
343   if ( myNbElements < 2 )
344   {
345     return boost::make_shared< EArrayIterator >( elem1st, elem1st + myNbElements );
346   }
347
348   return myParent->shapeElementsIterator( myIndex, myNbElements, *elem1st );
349 }
350
351 //=======================================================================
352 //function : GetNodes
353 //purpose  :
354 //=======================================================================
355
356 SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const
357 {
358   if ( IsComplexSubmesh() )
359     return SMDS_NodeIteratorPtr( new MyNodeIterator( mySubMeshes ));
360
361   PNode const * node1st =
362     reinterpret_cast< PNode const* >( & my1stElemNode[ ind1st( SMDSAbs_Node )] );
363   if ( myNbNodes < 2 )
364   {
365     return boost::make_shared< NArrayIterator >( node1st, node1st + myNbNodes );
366   }
367
368   return myParent->shapeNodesIterator( myIndex, myNbNodes, *node1st );
369 }
370
371 //=======================================================================
372 //function : Contains
373 //purpose  : check if elem or node is in
374 //=======================================================================
375
376 bool SMESHDS_SubMesh::Contains(const SMDS_MeshElement * ME) const
377 {
378   if ( !ME || ME->IsNull() )
379     return false;
380
381   if ( IsComplexSubmesh() )
382   {
383     TSubMeshSet::const_iterator aSubIt = mySubMeshes.begin();
384     for (; aSubIt != mySubMeshes.end(); aSubIt++)
385       if ((*aSubIt)->Contains(ME))
386         return true;
387     return false;
388   }
389   return ME->getshapeId() == myIndex;
390 }
391
392 //=======================================================================
393 //function : IsQuadratic
394 //purpose  : Return true if my 1st element is quadratic
395 //=======================================================================
396
397 bool SMESHDS_SubMesh::IsQuadratic() const
398 {
399   if ( IsComplexSubmesh() )
400   {
401     TSubMeshSet::const_iterator aSubIt = mySubMeshes.begin();
402     for (; aSubIt != mySubMeshes.end(); aSubIt++)
403       if ((*aSubIt)->IsQuadratic())
404         return true;
405     return false;
406   }
407
408   if ( myNbElements == 0 )
409     return false;
410
411   SMDS_ElemIteratorPtr it = GetElements();
412   return it->more() && it->next()->IsQuadratic();
413 }
414
415 //=======================================================================
416 //function : AddSubMesh
417 //purpose  :
418 //=======================================================================
419
420 void SMESHDS_SubMesh::AddSubMesh( const SMESHDS_SubMesh* theSubMesh )
421 {
422   ASSERT( theSubMesh );
423   mySubMeshes.insert( theSubMesh );
424 }
425
426 //=======================================================================
427 //function : RemoveSubMesh
428 //purpose  : 
429 //=======================================================================
430
431 bool SMESHDS_SubMesh::RemoveSubMesh( const SMESHDS_SubMesh* theSubMesh )
432 {
433   return mySubMeshes.erase( theSubMesh );
434 }
435
436 //=======================================================================
437 //function : RemoveAllSubmeshes
438 //purpose  : 
439 //=======================================================================
440
441 void SMESHDS_SubMesh::RemoveAllSubmeshes()
442 {
443   mySubMeshes.clear();
444 }
445
446 //=======================================================================
447 //function : ContainsSubMesh
448 //purpose  :
449 //=======================================================================
450
451 bool SMESHDS_SubMesh::ContainsSubMesh( const SMESHDS_SubMesh* theSubMesh ) const
452 {
453   return mySubMeshes.find( theSubMesh ) != mySubMeshes.end();
454 }
455
456 //=======================================================================
457 //function : GetSubMeshIterator
458 //purpose  :
459 //=======================================================================
460
461 SMESHDS_SubMeshIteratorPtr SMESHDS_SubMesh::GetSubMeshIterator() const
462 {
463   typedef SMDS_SetIterator< const SMESHDS_SubMesh*, TSubMeshSet::const_iterator > TIterator;
464   return boost::make_shared< TIterator >( mySubMeshes.begin(), mySubMeshes.end());
465 }
466
467 //=======================================================================
468 //function : Clear
469 //purpose  : remove the contents
470 //=======================================================================
471
472 void SMESHDS_SubMesh::Clear()
473 {
474   if ( myParent && myParent->NbNodes() > 0 )
475   {
476     if ( myNbElements > 0 )
477       for ( SMDS_ElemIteratorPtr it = GetElements(); it->more(); )
478       {
479         const SMDS_MeshElement * elem = it->next();
480         elem->setShapeID( 0 );
481       }
482     if ( myNbNodes > 0 )
483       for ( SMDS_NodeIteratorPtr it = GetNodes(); it->more(); )
484       {
485         const SMDS_MeshNode * elem = it->next();
486         elem->setShapeID( 0 );
487       }
488   }
489
490   myNbElements = 0;
491   myNbNodes = 0;
492   my1stElemNode[0] = my1stElemNode[1] = 0;
493
494   if ( NbSubMeshes() > 0 )
495   {
496     SMESHDS_SubMeshIteratorPtr sub = GetSubMeshIterator();
497     while ( sub->more() ) {
498       if ( SMESHDS_SubMesh* sm = (SMESHDS_SubMesh*) sub->next())
499         sm->Clear();
500     }
501   }
502 }
503
504 //=======================================================================
505 //function : getElements
506 //purpose  : Return iterator on all elements and nodes during compacting
507 //=======================================================================
508
509 SMDS_ElemIteratorPtr SMESHDS_SubMesh::getElements()
510 {
511   if ( IsComplexSubmesh() ) // return nothing
512     boost::make_shared< EArrayIterator >( & my1stElemNode[0], & my1stElemNode[0] );
513
514   typedef std::vector< SMDS_ElemIteratorPtr > TIterVec;
515   TIterVec iterVec(2);
516   iterVec[0] = GetElements();
517   iterVec[1].reset( new _MyElemIteratorFromNodeIterator( GetNodes() ));
518
519   return boost::make_shared< SMDS_IteratorOnIterators< PElem, TIterVec > >( iterVec );
520 }
521
522 //=======================================================================
523 //function : tmpClear
524 //purpose  : clean up after compacting
525 //=======================================================================
526
527 void SMESHDS_SubMesh::tmpClear()
528 {
529   my1stElemNode[0] = my1stElemNode[1] = 0;
530 }
531
532 //=======================================================================
533 //function : add
534 //purpose  : update my1stElemNode
535 //=======================================================================
536
537 void SMESHDS_SubMesh::add( const SMDS_MeshElement* elem )
538 {
539   const SMDS_MeshElement* & oldElem = my1stElemNode[ ind1st( elem->GetType() )];
540   if ( !oldElem || oldElem->GetID() > elem->GetID() )
541     oldElem = elem;
542 }