Salome HOME
Update copyright
[modules/smesh.git] / src / SMESH_I / SMESH_subMesh_i.cxx
1 // Copyright (C) 2007-2011  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 SMESH_I : idl implementation based on 'SMESH' unit's calsses
24 //  File   : SMESH_subMesh_i.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //  $Header$
28 //
29 #include "SMESH_subMesh_i.hxx"
30 #include "SMESH_Gen_i.hxx"
31 #include "SMESH_Mesh_i.hxx"
32
33 #include "Utils_CorbaException.hxx"
34 #include "utilities.h"
35 #include "OpUtil.hxx"
36 #include "Utils_ExceptHandlers.hxx"
37
38 #include <TopoDS_Iterator.hxx>
39 #include <TopExp_Explorer.hxx>
40
41 using namespace std;
42
43 //=============================================================================
44 /*!
45  *  
46  */
47 //=============================================================================
48
49 SMESH_subMesh_i::SMESH_subMesh_i()
50      : SALOME::GenericObj_i( PortableServer::POA::_nil() )
51 {
52   MESSAGE("SMESH_subMesh_i::SMESH_subMesh_i default, not for use");
53     ASSERT(0);
54 }
55
56 //=============================================================================
57 /*!
58  *  
59  */
60 //=============================================================================
61
62 SMESH_subMesh_i::SMESH_subMesh_i( PortableServer::POA_ptr thePOA,
63                                   SMESH_Gen_i*            gen_i,
64                                   SMESH_Mesh_i*           mesh_i,
65                                   int                     localId )
66      : SALOME::GenericObj_i( thePOA )
67 {
68   MESSAGE("SMESH_subMesh_i::SMESH_subMesh_i");
69   _gen_i = gen_i;
70   _mesh_i = mesh_i;
71   _localId = localId;
72   // ****
73 }
74 //=============================================================================
75 /*!
76  *  
77  */
78 //=============================================================================
79
80 SMESH_subMesh_i::~SMESH_subMesh_i()
81 {
82   MESSAGE("SMESH_subMesh_i::~SMESH_subMesh_i");
83   // ****
84 }
85
86 //=======================================================================
87 //function : getSubMeshes
88 //purpose  : for a submesh on shape to which elements are not bound directly,
89 //           return submeshes containing elements
90 //=======================================================================
91
92 typedef list<SMESHDS_SubMesh*> TListOfSubMeshes;
93
94 bool getSubMeshes(::SMESH_subMesh*  theSubMesh,
95                   TListOfSubMeshes& theSubMeshList)
96 {
97   int size = theSubMeshList.size();
98
99   SMESH_Mesh*      aMesh      = theSubMesh->GetFather();
100   SMESHDS_Mesh*    aMeshDS    = aMesh->GetMeshDS();
101   SMESHDS_SubMesh* aSubMeshDS = theSubMesh->GetSubMeshDS();
102
103   // nodes can be bound to either vertex, edge, face or solid_or_shell
104   TopoDS_Shape aShape = theSubMesh->GetSubShape();
105   switch ( aShape.ShapeType() )
106   {
107   case TopAbs_SOLID: {
108     // add submesh of solid itself
109     aSubMeshDS = aMeshDS->MeshElements( aShape );
110     if ( aSubMeshDS )
111       theSubMeshList.push_back( aSubMeshDS );
112     // and of the first shell
113     TopExp_Explorer exp( aShape, TopAbs_SHELL );
114     if ( exp.More() ) {
115       aSubMeshDS = aMeshDS->MeshElements( exp.Current() );
116       if ( aSubMeshDS )
117         theSubMeshList.push_back( aSubMeshDS );
118     }
119     break;
120   }
121   case TopAbs_WIRE:
122   case TopAbs_COMPOUND:
123   case TopAbs_COMPSOLID: {
124     // call getSubMeshes() for sub-shapes
125     list<TopoDS_Shape> shapeList;
126     shapeList.push_back( aShape );
127     list<TopoDS_Shape>::iterator sh = shapeList.begin();
128     for ( ; sh != shapeList.end(); ++sh ) {
129       for ( TopoDS_Iterator it( *sh ); it.More(); it.Next() ) {
130         if ( ::SMESH_subMesh* aSubMesh = aMesh->GetSubMeshContaining( it.Value() ))
131           getSubMeshes( aSubMesh, theSubMeshList ); // add found submesh or explore deeper
132         else
133           // no submesh for a compound inside compound
134           shapeList.push_back( it.Value() );
135       }
136     }
137     // return only unique submeshes
138     set<SMESHDS_SubMesh*> smSet;
139     TListOfSubMeshes::iterator sm = theSubMeshList.begin();
140     while ( sm != theSubMeshList.end() ) {
141       if ( !smSet.insert( *sm ).second )
142         sm = theSubMeshList.erase( sm );
143       else
144         ++sm;
145     }
146     break;
147   }
148   default:
149     if ( aSubMeshDS )
150       theSubMeshList.push_back( aSubMeshDS );
151   }
152   return size < theSubMeshList.size();
153 }
154
155 //=============================================================================
156 /*!
157  *  
158  */
159 //=============================================================================
160
161 CORBA::Long SMESH_subMesh_i::GetNumberOfElements()
162   throw (SALOME::SALOME_Exception)
163 {
164   Unexpect aCatch(SALOME_SalomeException);
165   MESSAGE("SMESH_subMesh_i::GetNumberOfElements");
166   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
167     return 0;
168
169   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
170   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
171
172   int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
173
174   // volumes are bound to shell
175   TListOfSubMeshes smList;
176   if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
177   {
178     TListOfSubMeshes::iterator sm = smList.begin();
179     for ( ; sm != smList.end(); ++sm )
180       nbElems += (*sm)->NbElements();
181   }
182   return nbElems;
183 }
184
185 //=============================================================================
186 /*!
187  *  
188  */
189 //=============================================================================
190
191 CORBA::Long SMESH_subMesh_i::GetNumberOfNodes(CORBA::Boolean all)
192   throw (SALOME::SALOME_Exception)
193 {
194   Unexpect aCatch(SALOME_SalomeException);
195   MESSAGE("SMESH_subMesh_i::GetNumberOfNodes");
196   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
197     return 0;
198
199   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
200   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
201
202   set<int> nodeIds;
203
204   // nodes are bound to shell instead of solid
205   TListOfSubMeshes smList;
206   if ( all && getSubMeshes( aSubMesh, smList ))
207   {
208     TListOfSubMeshes::iterator sm = smList.begin();
209     for ( ; sm != smList.end(); ++sm )
210     {
211       SMDS_ElemIteratorPtr eIt = (*sm)->GetElements();
212       if ( eIt->more() ) {
213         while ( eIt->more() ) {
214           const SMDS_MeshElement* anElem = eIt->next();
215           SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
216           while ( nIt->more() )
217             nodeIds.insert( nIt->next()->GetID() );
218         }
219       } else {
220         SMDS_NodeIteratorPtr nIt = (*sm)->GetNodes();
221         while ( nIt->more() )
222           nodeIds.insert( nIt->next()->GetID() );
223       }      
224     }
225     return nodeIds.size();
226   }
227
228   if ( aSubMeshDS == NULL )
229     return 0;
230
231   if ( all ) { // all nodes of submesh elements
232     SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
233     if ( eIt->more() ) {
234       while ( eIt->more() ) {
235         const SMDS_MeshElement* anElem = eIt->next();
236         SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
237         while ( nIt->more() )
238           nodeIds.insert( nIt->next()->GetID() );
239       }
240     } else {
241       SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes();
242       while ( nIt->more() )
243         nodeIds.insert( nIt->next()->GetID() );
244     }
245     return nodeIds.size();
246   }
247
248   return aSubMeshDS->NbNodes();
249 }
250
251 //=============================================================================
252 /*!
253  *  
254  */
255 //=============================================================================
256
257 SMESH::long_array* SMESH_subMesh_i::GetElementsId()
258   throw (SALOME::SALOME_Exception)
259 {
260   Unexpect aCatch(SALOME_SalomeException);
261   MESSAGE("SMESH_subMesh_i::GetElementsId");
262   SMESH::long_array_var aResult = new SMESH::long_array();
263
264   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
265     return aResult._retn();
266
267   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
268   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
269
270   int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
271   TListOfSubMeshes smList;
272   if ( nbElems )
273     smList.push_back( aSubMeshDS );
274
275   // volumes are bound to shell
276   if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
277   {
278     TListOfSubMeshes::iterator sm = smList.begin();
279     for ( ; sm != smList.end(); ++sm )
280       nbElems += (*sm)->NbElements();
281   }
282
283   aResult->length( nbElems );
284   if ( nbElems )
285   {
286     TListOfSubMeshes::iterator sm = smList.begin();
287     for ( int i = 0; sm != smList.end(); sm++ )
288     {
289       SMDS_ElemIteratorPtr anIt = (*sm)->GetElements();
290       for ( ; i < nbElems && anIt->more(); i++ )
291         aResult[i] = anIt->next()->GetID();
292     }
293   }
294   return aResult._retn();
295 }
296
297
298 //=============================================================================
299 /*!
300  *  
301  */
302 //=============================================================================
303
304 SMESH::long_array* SMESH_subMesh_i::GetElementsByType( SMESH::ElementType theElemType )
305     throw (SALOME::SALOME_Exception)
306 {
307   Unexpect aCatch(SALOME_SalomeException);
308   MESSAGE("SMESH_subMesh_i::GetElementsByType");
309   SMESH::long_array_var aResult = new SMESH::long_array();
310
311   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
312     return aResult._retn();
313
314   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
315   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
316
317   // PAL5440, return all nodes belonging to elements of submesh
318   set<int> nodeIds;
319   int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
320
321   // volumes may be bound to shell instead of solid
322   TListOfSubMeshes smList;
323   if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
324   {
325     TListOfSubMeshes::iterator sm = smList.begin();
326     for ( ; sm != smList.end(); ++sm )
327     {
328       if ( theElemType == SMESH::NODE )
329       {
330         SMDS_ElemIteratorPtr eIt = (*sm)->GetElements();
331         if ( eIt->more() ) {
332           while ( eIt->more() ) {
333             const SMDS_MeshElement* anElem = eIt->next();
334             SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
335             while ( nIt->more() )
336               nodeIds.insert( nIt->next()->GetID() );
337           }
338         } else {
339           SMDS_NodeIteratorPtr nIt = (*sm)->GetNodes();
340           while ( nIt->more() )
341             nodeIds.insert( nIt->next()->GetID() );
342         }
343       }
344       else
345       {
346         nbElems += (*sm)->NbElements();
347       }
348     }
349     aSubMeshDS = 0;
350   }
351   else
352   {
353     if ( nbElems )
354       smList.push_back( aSubMeshDS );
355   }
356
357   if ( theElemType == SMESH::NODE && aSubMeshDS )
358   {
359     SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
360     if ( eIt->more() ) {
361       while ( eIt->more() ) {
362         const SMDS_MeshElement* anElem = eIt->next();
363         SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
364         while ( nIt->more() )
365           nodeIds.insert( nIt->next()->GetID() );
366       }
367     } else {
368       SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes();
369       while ( nIt->more() )
370         nodeIds.insert( nIt->next()->GetID() );
371     }
372   }
373
374   if ( theElemType == SMESH::NODE )
375     aResult->length( nodeIds.size() );
376   else
377     aResult->length( nbElems );
378
379   int i = 0, n = aResult->length();
380
381   if ( theElemType == SMESH::NODE && !nodeIds.empty() ) {
382     set<int>::iterator idIt = nodeIds.begin();
383     for ( ; i < n && idIt != nodeIds.end() ; i++, idIt++ )
384       aResult[i] = *idIt;
385   }
386
387   if ( theElemType != SMESH::NODE ) {
388     TListOfSubMeshes::iterator sm = smList.begin();
389     for ( i = 0; sm != smList.end(); sm++ )
390     {
391       aSubMeshDS = *sm;
392       SMDS_ElemIteratorPtr anIt = aSubMeshDS->GetElements();
393       while ( i < n && anIt->more() ) {
394         const SMDS_MeshElement* anElem = anIt->next();
395         if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
396           aResult[i++] = anElem->GetID();
397       }
398     }
399   }
400
401   aResult->length( i );
402
403   return aResult._retn();
404 }
405
406 //=============================================================================
407 /*!
408  *  
409  */
410 //=============================================================================
411   
412 SMESH::long_array* SMESH_subMesh_i::GetNodesId()
413   throw (SALOME::SALOME_Exception)
414 {
415   Unexpect aCatch(SALOME_SalomeException);
416   MESSAGE("SMESH_subMesh_i::GetNodesId");
417   SMESH::long_array_var aResult = GetElementsByType( SMESH::NODE );
418   return aResult._retn();
419 }
420
421 //=============================================================================
422 /*!
423  *  
424  */
425 //=============================================================================
426   
427 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetFather()
428   throw (SALOME::SALOME_Exception)
429 {
430   Unexpect aCatch(SALOME_SalomeException);
431   MESSAGE("SMESH_subMesh_i::GetFather");
432   return _mesh_i->_this();
433 }
434
435 //=============================================================================
436 /*!
437  *  
438  */
439 //=============================================================================
440   
441 CORBA::Long SMESH_subMesh_i::GetId()
442 {
443   MESSAGE("SMESH_subMesh_i::GetId");
444   return _localId;
445 }
446
447 //=======================================================================
448 //function : GetSubShape
449 //purpose  : 
450 //=======================================================================
451
452 GEOM::GEOM_Object_ptr SMESH_subMesh_i::GetSubShape()
453      throw (SALOME::SALOME_Exception)
454 {
455   Unexpect aCatch(SALOME_SalomeException);
456   GEOM::GEOM_Object_var aShapeObj;
457   try {
458     if ( _mesh_i->_mapSubMesh.find( _localId ) != _mesh_i->_mapSubMesh.end()) {
459       TopoDS_Shape S = _mesh_i->_mapSubMesh[ _localId ]->GetSubShape();
460       if ( !S.IsNull() ) {
461         aShapeObj = _gen_i->ShapeToGeomObject( S );
462         //mzn: N7PAL16232, N7PAL16233
463         //In some cases it's possible that GEOM_Client contains the shape same to S, but
464         //with another orientation.
465         if (aShapeObj->_is_nil())
466           aShapeObj = _gen_i->ShapeToGeomObject( S.Reversed() );
467       }
468     }
469   }
470   catch(SALOME_Exception & S_ex) {
471     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
472   }
473   return aShapeObj._retn();
474 }
475
476 //=============================================================================
477 /*!
478  *  
479  */
480 //=============================================================================
481 SALOME_MED::FAMILY_ptr SMESH_subMesh_i::GetFamily()
482   throw (SALOME::SALOME_Exception)
483 {
484   Unexpect aCatch(SALOME_SalomeException);
485   SALOME_MED::MESH_var MEDMesh = GetFather()->GetMEDMesh();
486
487   SALOME_MED::Family_array_var families = 
488     MEDMesh->getFamilies(SALOME_MED::MED_NODE);
489     
490   for ( int i = 0; i < families->length(); i++ ) {
491     if ( families[i]->getIdentifier() == ( _localId ) )
492       return families[i];
493   }
494   
495   return SALOME_MED::FAMILY::_nil();
496 }
497
498 //=============================================================================
499 /*!
500  *  
501  */
502 //=============================================================================
503 SMESH::long_array* SMESH_subMesh_i::GetIDs()
504 {
505   SMESH::long_array_var aResult = GetElementsId();
506   return aResult._retn();
507 }
508
509 //=============================================================================
510 /*!
511  *
512  */
513 //=============================================================================
514 SMESH::ElementType SMESH_subMesh_i::GetElementType( const CORBA::Long id, const bool iselem )
515   throw (SALOME::SALOME_Exception)
516 {
517   return GetFather()->GetElementType( id, iselem );
518 }
519
520
521 //=============================================================================
522 /*!
523  * Returns statistic of mesh elements
524  * Result array of number enityties
525  * Inherited from SMESH_IDSource
526  */
527 //=============================================================================
528 SMESH::long_array* SMESH_subMesh_i::GetMeshInfo()
529 {
530   SMESH::long_array_var aRes = new SMESH::long_array();
531   aRes->length(SMESH::Entity_Last);
532   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
533     aRes[i] = 0;
534   
535   // get number of nodes
536   aRes[ SMESH::Entity_Node ] = GetNumberOfNodes(true);
537  
538   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
539
540   // get statistic from child sub-meshes
541   TListOfSubMeshes smList;
542   if ( getSubMeshes( aSubMesh, smList ) )
543     for ( TListOfSubMeshes::iterator sm = smList.begin(); sm != smList.end(); ++sm )
544       SMESH_Mesh_i::CollectMeshInfo( (*sm)->GetElements(), aRes );
545
546   return aRes._retn();
547 }
548
549
550 //=======================================================================
551 //function : GetTypes
552 //purpose  : Returns types of elements it contains
553 //=======================================================================
554
555 SMESH::array_of_ElementType* SMESH_subMesh_i::GetTypes()
556 {
557   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
558
559   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
560   TopoDS_Shape shape = aSubMesh->GetSubShape();
561   while ( !shape.IsNull() && shape.ShapeType() == TopAbs_COMPOUND )
562   {
563     TopoDS_Iterator it( shape );
564     shape = it.More() ? it.Value() : TopoDS_Shape();
565   }
566   if ( !shape.IsNull() )
567   {
568     types->length( 1 );
569     switch ( ::SMESH_Gen::GetShapeDim( shape ))
570     {
571     case 0: types[0] = SMESH::ELEM0D; break;
572     case 1: types[0] = SMESH::EDGE; break;
573     case 2: types[0] = SMESH::FACE; break;
574     case 3: types[0] = SMESH::VOLUME; break;
575     default:
576       types->length(0);
577     }
578   }
579   return types._retn();
580 }
581
582 //=======================================================================
583 //function : GetMesh
584 //purpose  : interface SMESH_IDSource
585 //=======================================================================
586
587 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetMesh()
588 {
589   return GetFather();
590 }