Salome HOME
Regression of SALOME_TESTS/Grids/smesh/3D_mesh_Extrusion_01/B8
[modules/smesh.git] / src / SMESHDS / SMESHDS_SubMesh.cxx
1 // Copyright (C) 2007-2016  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(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
119     elem->setShapeID( myIndex );
120     myNbElements++;
121
122     // remember element with smallest ID to optimize iteration on them
123     add( elem );
124   }
125 }
126
127 //=======================================================================
128 //function : RemoveElement
129 //purpose  :
130 //=======================================================================
131
132 bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * elem )
133 {
134   if ( !elem || elem->IsNull() || elem->getshapeId() != myIndex )
135   {
136     return false;
137   }
138   if ( !IsComplexSubmesh() )
139   {
140     elem->setShapeID( 0 );
141     myNbElements--;
142
143     const SMDS_MeshElement* & elem1st = my1stElemNode[ ind1st( elem->GetType() )];
144     if ( elem1st == elem )
145       elem1st = 0;
146
147     return true;
148   }
149   return false;
150 }
151
152 //=======================================================================
153 //function : AddNode
154 //purpose  :
155 //=======================================================================
156
157 void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
158 {
159   if ( !IsComplexSubmesh() )
160   {
161     const int shapeId = N->getshapeId();
162     if ( shapeId > 0 )
163     {
164       if ( shapeId != myIndex )
165         throw SALOME_Exception
166           (LOCALIZED("a node being in sub-mesh is added to another sub-mesh"));
167       return; // already in
168     }
169     N->setShapeID( myIndex );
170     myNbNodes++;
171
172     // remember node with smallest ID to optimize iteration on them
173     add( N );
174   }
175 }
176
177 //=======================================================================
178 //function : RemoveNode
179 //purpose  :
180 //=======================================================================
181
182 bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N)
183 {
184   if ( !N || N->getshapeId() != myIndex )
185   {
186     return false;
187   }
188   if ( !IsComplexSubmesh() )
189   {
190     N->setShapeID( 0 );
191     myNbNodes--;
192
193     const SMDS_MeshElement* & node1st = my1stElemNode[ ind1st( SMDSAbs_Node )];
194     if ( node1st == N )
195       node1st = 0;
196
197     return true;
198   }
199   return false;
200 }
201
202 //=======================================================================
203 //function : NbElements
204 //purpose  :
205 //=======================================================================
206
207 int SMESHDS_SubMesh::NbElements() const
208 {
209   if ( !IsComplexSubmesh() )
210     return myNbElements;
211
212   int nbElems = 0;
213   TSubMeshSet::const_iterator it = mySubMeshes.begin();
214   for ( ; it != mySubMeshes.end(); it++ )
215     nbElems += (*it)->NbElements();
216
217   return nbElems;
218 }
219
220 //=======================================================================
221 //function : NbNodes
222 //purpose  :
223 //=======================================================================
224
225 int SMESHDS_SubMesh::NbNodes() const
226 {
227   if ( !IsComplexSubmesh() )
228     return myNbNodes;
229
230   int nbElems = 0;
231   TSubMeshSet::const_iterator it = mySubMeshes.begin();
232   for ( ; it != mySubMeshes.end(); it++ )
233     nbElems += (*it)->NbNodes();
234
235   return nbElems;
236 }
237
238 // =====================
239 // class MyIterator
240 // =====================
241
242 template<typename VALUE> class MyIterator : public SMDS_Iterator<VALUE>
243 {
244 public:
245   MyIterator (const TSubMeshSet& theSubMeshes)
246     : myMore(false), mySubIt( theSubMeshes.begin() ), mySubEnd( theSubMeshes.end() )
247   {}
248   bool more()
249   {
250     while (( !myElemIt.get() || !myElemIt->more() ) && mySubIt != mySubEnd)
251     {
252       myElemIt = getElements(*mySubIt);
253       mySubIt++;
254     }
255     myMore = myElemIt.get() && myElemIt->more();
256     return myMore;
257   }
258   VALUE next()
259   {
260     VALUE elem = 0;
261     if ( myMore )
262       elem = myElemIt->next();
263     return elem;
264   }
265 protected:
266   virtual boost::shared_ptr< SMDS_Iterator<VALUE> >
267   getElements(const SMESHDS_SubMesh*) const = 0;
268
269 private:
270   bool                                      myMore;
271   TSubMeshSet::const_iterator               mySubIt, mySubEnd;
272   boost::shared_ptr< SMDS_Iterator<VALUE> > myElemIt;
273 };
274
275 // =====================
276 // class MyElemIterator
277 // =====================
278
279 class MyElemIterator: public MyIterator<const SMDS_MeshElement*>
280 {
281 public:
282   MyElemIterator (const TSubMeshSet& theSubMeshes)
283     :MyIterator<const SMDS_MeshElement*>( theSubMeshes ) {}
284   SMDS_ElemIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
285   { return theSubMesh->GetElements(); }
286 };
287
288 // =====================
289 // class MyNodeIterator
290 // =====================
291
292 class MyNodeIterator: public MyIterator<const SMDS_MeshNode*>
293 {
294 public:
295   MyNodeIterator (const TSubMeshSet& theSubMeshes)
296     :MyIterator<const SMDS_MeshNode*>( theSubMeshes ) {}
297   SMDS_NodeIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
298   { return theSubMesh->GetNodes(); }
299 };
300
301 //=======================================================================
302 //function : GetElements
303 //purpose  :
304 //=======================================================================
305
306 SMDS_ElemIteratorPtr SMESHDS_SubMesh::GetElements() const
307 {
308   if ( IsComplexSubmesh() )
309     return SMDS_ElemIteratorPtr( new MyElemIterator( mySubMeshes ));
310
311   const SMDS_MeshElement* const * elem1st = & my1stElemNode[ ind1st( SMDSAbs_All )];
312   if ( myNbElements == 1 )
313   {
314     return boost::make_shared< EArrayIterator >( elem1st, elem1st+1 );
315   }
316
317   return myParent->shapeElementsIterator( myIndex, myNbElements, *elem1st );
318 }
319
320 //=======================================================================
321 //function : GetNodes
322 //purpose  :
323 //=======================================================================
324
325 SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const
326 {
327   if ( IsComplexSubmesh() )
328     return SMDS_NodeIteratorPtr( new MyNodeIterator( mySubMeshes ));
329
330   PNode const * node1st =
331     reinterpret_cast< PNode const* >( & my1stElemNode[ ind1st( SMDSAbs_Node )] );
332   if ( myNbNodes == 1 )
333   {
334     return boost::make_shared< NArrayIterator >( node1st, node1st+1 );
335   }
336
337   return myParent->shapeNodesIterator( myIndex, myNbNodes, *node1st );
338 }
339
340 //=======================================================================
341 //function : Contains
342 //purpose  : check if elem or node is in
343 //=======================================================================
344
345 bool SMESHDS_SubMesh::Contains(const SMDS_MeshElement * ME) const
346 {
347   if ( !ME || ME->IsNull() )
348     return false;
349
350   if ( IsComplexSubmesh() )
351   {
352     TSubMeshSet::const_iterator aSubIt = mySubMeshes.begin();
353     for (; aSubIt != mySubMeshes.end(); aSubIt++)
354       if ((*aSubIt)->Contains(ME))
355         return true;
356     return false;
357   }
358   return ME->getshapeId() == myIndex;
359 }
360
361 //=======================================================================
362 //function : IsQuadratic
363 //purpose  : Return true if my 1st element is quadratic
364 //=======================================================================
365
366 bool SMESHDS_SubMesh::IsQuadratic() const
367 {
368   if ( IsComplexSubmesh() )
369   {
370     TSubMeshSet::const_iterator aSubIt = mySubMeshes.begin();
371     for (; aSubIt != mySubMeshes.end(); aSubIt++)
372       if ((*aSubIt)->IsQuadratic())
373         return true;
374     return false;
375   }
376
377   if ( myNbElements == 0 )
378     return false;
379
380   SMDS_ElemIteratorPtr it = GetElements();
381   return it->more() && it->next()->IsQuadratic();
382 }
383
384 //=======================================================================
385 //function : AddSubMesh
386 //purpose  :
387 //=======================================================================
388
389 void SMESHDS_SubMesh::AddSubMesh( const SMESHDS_SubMesh* theSubMesh )
390 {
391   ASSERT( theSubMesh );
392   mySubMeshes.insert( theSubMesh );
393 }
394
395 //=======================================================================
396 //function : RemoveSubMesh
397 //purpose  : 
398 //=======================================================================
399
400 bool SMESHDS_SubMesh::RemoveSubMesh( const SMESHDS_SubMesh* theSubMesh )
401 {
402   return mySubMeshes.erase( theSubMesh );
403 }
404
405 //=======================================================================
406 //function : RemoveAllSubmeshes
407 //purpose  : 
408 //=======================================================================
409
410 void SMESHDS_SubMesh::RemoveAllSubmeshes()
411 {
412   mySubMeshes.clear();
413 }
414
415 //=======================================================================
416 //function : ContainsSubMesh
417 //purpose  :
418 //=======================================================================
419
420 bool SMESHDS_SubMesh::ContainsSubMesh( const SMESHDS_SubMesh* theSubMesh ) const
421 {
422   return mySubMeshes.find( theSubMesh ) != mySubMeshes.end();
423 }
424
425 //=======================================================================
426 //function : GetSubMeshIterator
427 //purpose  :
428 //=======================================================================
429
430 SMESHDS_SubMeshIteratorPtr SMESHDS_SubMesh::GetSubMeshIterator() const
431 {
432   typedef SMDS_SetIterator< const SMESHDS_SubMesh*, TSubMeshSet::const_iterator > TIterator;
433   return boost::make_shared< TIterator >( mySubMeshes.begin(), mySubMeshes.end());
434 }
435
436 //=======================================================================
437 //function : Clear
438 //purpose  : remove the contents
439 //=======================================================================
440
441 void SMESHDS_SubMesh::Clear()
442 {
443   if ( myParent && myParent->NbNodes() > 0 )
444   {
445     if ( myNbElements > 0 )
446       for ( SMDS_ElemIteratorPtr it = GetElements(); it->more(); )
447       {
448         const SMDS_MeshElement * elem = it->next();
449         elem->setShapeID( 0 );
450       }
451     if ( myNbNodes > 0 )
452       for ( SMDS_NodeIteratorPtr it = GetNodes(); it->more(); )
453       {
454         const SMDS_MeshNode * elem = it->next();
455         elem->setShapeID( 0 );
456       }
457   }
458
459   myNbElements = 0;
460   myNbNodes = 0;
461   my1stElemNode[0] = my1stElemNode[1] = 0;
462   if ( NbSubMeshes() > 0 )
463   {
464     SMESHDS_SubMeshIteratorPtr sub = GetSubMeshIterator();
465     while ( sub->more() ) {
466       if ( SMESHDS_SubMesh* sm = (SMESHDS_SubMesh*) sub->next())
467         sm->Clear();
468     }
469   }
470 }
471
472 //=======================================================================
473 //function : getElements
474 //purpose  : Return iterator on all elements and nodes during compacting
475 //=======================================================================
476
477 SMDS_ElemIteratorPtr SMESHDS_SubMesh::getElements()
478 {
479   if ( IsComplexSubmesh() ) // return nothing
480     boost::make_shared< EArrayIterator >( & my1stElemNode[0], & my1stElemNode[0] );
481
482   typedef std::vector< SMDS_ElemIteratorPtr > TIterVec;
483   TIterVec iterVec(2);
484   iterVec[0] = GetElements();
485   iterVec[1].reset( new _MyElemIteratorFromNodeIterator( GetNodes() ));
486
487   return boost::make_shared< SMDS_IteratorOnIterators< PElem, TIterVec > >( iterVec );
488 }
489
490 //=======================================================================
491 //function : tmpClear
492 //purpose  : clean up after compacting
493 //=======================================================================
494
495 void SMESHDS_SubMesh::tmpClear()
496 {
497   my1stElemNode[0] = my1stElemNode[1] = 0;
498 }
499
500 //=======================================================================
501 //function : add
502 //purpose  : update my1stElemNode
503 //=======================================================================
504
505 void SMESHDS_SubMesh::add( const SMDS_MeshElement* elem )
506 {
507   const SMDS_MeshElement* & oldElem = my1stElemNode[ ind1st( elem->GetType() )];
508   if ( !oldElem || oldElem->GetID() > elem->GetID() )
509     oldElem = elem;
510 }