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