Salome HOME
GetElementType method added
[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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SMESH_subMesh_i.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //  $Header$
28
29 using namespace std;
30 #include "SMESH_subMesh_i.hxx"
31 #include "SMESH_Gen_i.hxx"
32 #include "SMESH_Mesh_i.hxx"
33
34 #include "Utils_CorbaException.hxx"
35 #include "utilities.h"
36 #include "OpUtil.hxx"
37 #include "Utils_ExceptHandlers.hxx"
38
39 #include <BRepTools.hxx>
40 #include <TopoDS.hxx>
41 #include <TopoDS_Iterator.hxx>
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   thePOA->activate_object( this );
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         ::SMESH_subMesh* aSubMesh = aMesh->GetSubMeshContaining( it.Value() );
132         if ( aSubMesh )
133           getSubMeshes( aSubMesh, theSubMeshList );
134         else
135           // no submesh for a compound inside compound
136           shapeList.push_back( it.Value() );
137       }
138     }
139     // return only unique submeshes
140     set<SMESHDS_SubMesh*> smSet;
141     TListOfSubMeshes::iterator sm = theSubMeshList.begin();
142     while ( sm != theSubMeshList.end() ) {
143       if ( !smSet.insert( *sm ).second )
144         sm = theSubMeshList.erase( sm );
145       else
146         ++sm;
147     }
148     break;
149   }
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       while ( eIt->more() ) {
212         const SMDS_MeshElement* anElem = eIt->next();
213         SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
214         while ( nIt->more() )
215           nodeIds.insert( nIt->next()->GetID() );
216       }
217     }
218     return nodeIds.size();
219   }
220
221   if ( aSubMeshDS == NULL )
222     return 0;
223
224   if ( all ) { // all nodes of submesh elements
225     SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
226     while ( eIt->more() ) {
227       const SMDS_MeshElement* anElem = eIt->next();
228       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
229       while ( nIt->more() )
230         nodeIds.insert( nIt->next()->GetID() );
231     }
232     return nodeIds.size();
233   }
234     
235   return aSubMeshDS->NbNodes();
236 }
237
238 //=============================================================================
239 /*!
240  *  
241  */
242 //=============================================================================
243   
244 SMESH::long_array* SMESH_subMesh_i::GetElementsId()
245   throw (SALOME::SALOME_Exception)
246 {
247   Unexpect aCatch(SALOME_SalomeException);
248   MESSAGE("SMESH_subMesh_i::GetElementsId");
249   SMESH::long_array_var aResult = new SMESH::long_array();
250
251   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
252     return aResult._retn();
253
254   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
255   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
256
257   int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
258   TListOfSubMeshes smList;
259   if ( nbElems )
260     smList.push_back( aSubMeshDS );
261
262   // volumes are bound to shell
263   if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
264   {
265     TListOfSubMeshes::iterator sm = smList.begin();
266     for ( ; sm != smList.end(); ++sm )
267       nbElems += (*sm)->NbElements();
268   }
269
270   aResult->length( nbElems );
271   if ( nbElems )
272   {
273     TListOfSubMeshes::iterator sm = smList.begin();
274     for ( int i = 0; sm != smList.end(); sm++ )
275     {
276       SMDS_ElemIteratorPtr anIt = (*sm)->GetElements();
277       for ( int n = aSubMeshDS->NbElements(); i < n && anIt->more(); i++ )
278         aResult[i] = anIt->next()->GetID();
279     }
280   }
281   return aResult._retn();
282 }
283
284
285 //=============================================================================
286 /*!
287  *  
288  */
289 //=============================================================================
290
291 SMESH::long_array* SMESH_subMesh_i::GetElementsByType( SMESH::ElementType theElemType )
292     throw (SALOME::SALOME_Exception)
293 {
294   Unexpect aCatch(SALOME_SalomeException);
295   MESSAGE("SMESH_subMesh_i::GetElementsByType");
296   SMESH::long_array_var aResult = new SMESH::long_array();
297
298   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
299     return aResult._retn();
300
301   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
302   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
303
304   // PAL5440, return all nodes belonging to elements of submesh
305   set<int> nodeIds;
306   int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
307
308   // volumes may be bound to shell instead of solid
309   TListOfSubMeshes smList;
310   if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
311   {
312     TListOfSubMeshes::iterator sm = smList.begin();
313     for ( ; sm != smList.end(); ++sm )
314     {
315       if ( theElemType == SMESH::NODE )
316       {
317         SMDS_ElemIteratorPtr eIt = (*sm)->GetElements();
318         while ( eIt->more() ) {
319           const SMDS_MeshElement* anElem = eIt->next();
320           SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
321           while ( nIt->more() )
322             nodeIds.insert( nIt->next()->GetID() );
323         }
324       }
325       else
326       {
327         nbElems += (*sm)->NbElements();
328       }
329     }
330     aSubMeshDS = 0;
331   }
332   else
333   {
334     if ( nbElems )
335       smList.push_back( aSubMeshDS );
336   }
337
338   if ( theElemType == SMESH::NODE && aSubMeshDS )
339   {
340     SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
341     while ( eIt->more() ) {
342       const SMDS_MeshElement* anElem = eIt->next();
343       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
344       while ( nIt->more() )
345         nodeIds.insert( nIt->next()->GetID() );
346     }
347   }
348
349   if ( theElemType == SMESH::NODE )
350     aResult->length( nodeIds.size() );
351   else
352     aResult->length( nbElems );
353
354   int i = 0, n = aResult->length();
355
356   if ( theElemType == SMESH::NODE && !nodeIds.empty() ) {
357     set<int>::iterator idIt = nodeIds.begin();
358     for ( ; i < n && idIt != nodeIds.end() ; i++, idIt++ )
359       aResult[i] = *idIt;
360   }
361
362   if ( theElemType != SMESH::NODE ) {
363     TListOfSubMeshes::iterator sm = smList.begin();
364     for ( i = 0; sm != smList.end(); sm++ )
365     {
366       aSubMeshDS = *sm;
367       SMDS_ElemIteratorPtr anIt = aSubMeshDS->GetElements();
368       while ( i < n && anIt->more() ) {
369         const SMDS_MeshElement* anElem = anIt->next();
370         if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
371           aResult[i++] = anElem->GetID();
372       }
373     }
374   }
375
376   aResult->length( i );
377
378   return aResult._retn();
379 }
380
381 //=============================================================================
382 /*!
383  *  
384  */
385 //=============================================================================
386   
387 SMESH::long_array* SMESH_subMesh_i::GetNodesId()
388   throw (SALOME::SALOME_Exception)
389 {
390   Unexpect aCatch(SALOME_SalomeException);
391   MESSAGE("SMESH_subMesh_i::GetNodesId");
392   SMESH::long_array_var aResult = GetElementsByType( SMESH::NODE );
393   return aResult._retn();
394 }
395
396 //=============================================================================
397 /*!
398  *  
399  */
400 //=============================================================================
401   
402 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetFather()
403   throw (SALOME::SALOME_Exception)
404 {
405   Unexpect aCatch(SALOME_SalomeException);
406   MESSAGE("SMESH_subMesh_i::GetFather");
407   return _mesh_i->_this();
408 }
409
410 //=============================================================================
411 /*!
412  *  
413  */
414 //=============================================================================
415   
416 CORBA::Long SMESH_subMesh_i::GetId()
417 {
418   MESSAGE("SMESH_subMesh_i::GetId");
419   return _localId;
420 }
421
422 //=======================================================================
423 //function : GetSubShape
424 //purpose  : 
425 //=======================================================================
426
427 GEOM::GEOM_Object_ptr SMESH_subMesh_i::GetSubShape()
428      throw (SALOME::SALOME_Exception)
429 {
430   Unexpect aCatch(SALOME_SalomeException);
431   GEOM::GEOM_Object_var aShapeObj;
432   try {
433     if ( _mesh_i->_mapSubMesh.find( _localId ) != _mesh_i->_mapSubMesh.end()) {
434       TopoDS_Shape S = _mesh_i->_mapSubMesh[ _localId ]->GetSubShape();
435       if ( !S.IsNull() )
436         aShapeObj = _gen_i->ShapeToGeomObject( S );
437     }
438   }
439   catch(SALOME_Exception & S_ex) {
440     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
441   }
442   return aShapeObj._retn();
443 }
444
445 //=============================================================================
446 /*!
447  *  
448  */
449 //=============================================================================
450 SALOME_MED::FAMILY_ptr SMESH_subMesh_i::GetFamily()
451   throw (SALOME::SALOME_Exception)
452 {
453   Unexpect aCatch(SALOME_SalomeException);
454   SALOME_MED::MESH_var MEDMesh = GetFather()->GetMEDMesh();
455
456   SALOME_MED::Family_array_var families = 
457     MEDMesh->getFamilies(SALOME_MED::MED_NODE);
458     
459   for ( int i = 0; i < families->length(); i++ ) {
460     if ( families[i]->getIdentifier() == ( _localId ) )
461       return families[i];
462   }
463   
464   return SALOME_MED::FAMILY::_nil();
465 }
466
467 //=============================================================================
468 /*!
469  *  
470  */
471 //=============================================================================
472 SMESH::long_array* SMESH_subMesh_i::GetIDs()
473 {
474   SMESH::long_array_var aResult = GetElementsId();
475   return aResult._retn();
476 }
477
478 //=============================================================================
479 /*!
480  *
481  */
482 //=============================================================================
483 SMESH::ElementType SMESH_subMesh_i::GetElementType( const CORBA::Long id, const bool iselem )
484   throw (SALOME::SALOME_Exception)
485 {
486   return GetFather()->GetElementType( id, iselem );
487 }