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